diff options
author | petrcermak <petrcermak@chromium.org> | 2014-11-05 18:17:57 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-06 02:18:21 +0000 |
commit | 7652da6d5cbd7e5b82b340e638ebe80aafeacf6e (patch) | |
tree | 25110fc030ba4aa5d0b1c3e1ca14c62e2b6b4acd /base | |
parent | cac4fcac08708216009373121e573686adaac869 (diff) | |
download | chromium_src-7652da6d5cbd7e5b82b340e638ebe80aafeacf6e.zip chromium_src-7652da6d5cbd7e5b82b340e638ebe80aafeacf6e.tar.gz chromium_src-7652da6d5cbd7e5b82b340e638ebe80aafeacf6e.tar.bz2 |
Add support to base::Timer for custom task runners.
This patch adds a public method
SetTaskRunner(scoped_refptr<SingleThreadTaskRunner>) to base::Timer
which changes the task runner used by the timer
(ThreadTaskRunnerHandler::Get() by default).
This change will enable scheduling timers on the queues of the
Blink scheduler (see https://codereview.chromium.org/637303003/).
Most importantly, we plan to apply this to the shared timer in
blink::Platform.
BUG=
Review URL: https://codereview.chromium.org/637983003
Cr-Commit-Position: refs/heads/master@{#302947}
Diffstat (limited to 'base')
-rw-r--r-- | base/timer/timer.cc | 14 | ||||
-rw-r--r-- | base/timer/timer.h | 14 | ||||
-rw-r--r-- | base/timer/timer_unittest.cc | 37 |
3 files changed, 61 insertions, 4 deletions
diff --git a/base/timer/timer.cc b/base/timer/timer.cc index 1916ccc..11f73ca 100644 --- a/base/timer/timer.cc +++ b/base/timer/timer.cc @@ -93,6 +93,12 @@ TimeDelta Timer::GetCurrentDelay() const { return delay_; } +void Timer::SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner) { + // Do not allow changing the task runner once something has been scheduled. + DCHECK_EQ(thread_id_, 0); + task_runner_.swap(task_runner); +} + void Timer::Start(const tracked_objects::Location& posted_from, TimeDelta delay, const base::Closure& user_task) { @@ -146,12 +152,12 @@ void Timer::PostNewScheduledTask(TimeDelta delay) { is_running_ = true; scheduled_task_ = new BaseTimerTaskInternal(this); if (delay > TimeDelta::FromMicroseconds(0)) { - ThreadTaskRunnerHandle::Get()->PostDelayedTask(posted_from_, + GetTaskRunner()->PostDelayedTask(posted_from_, base::Bind(&BaseTimerTaskInternal::Run, base::Owned(scheduled_task_)), delay); scheduled_run_time_ = desired_run_time_ = TimeTicks::Now() + delay; } else { - ThreadTaskRunnerHandle::Get()->PostTask(posted_from_, + GetTaskRunner()->PostTask(posted_from_, base::Bind(&BaseTimerTaskInternal::Run, base::Owned(scheduled_task_))); scheduled_run_time_ = desired_run_time_ = TimeTicks(); } @@ -161,6 +167,10 @@ void Timer::PostNewScheduledTask(TimeDelta delay) { thread_id_ = static_cast<int>(PlatformThread::CurrentId()); } +scoped_refptr<SingleThreadTaskRunner> Timer::GetTaskRunner() { + return task_runner_.get() ? task_runner_ : ThreadTaskRunnerHandle::Get(); +} + void Timer::AbandonScheduledTask() { DCHECK(thread_id_ == 0 || thread_id_ == static_cast<int>(PlatformThread::CurrentId())); diff --git a/base/timer/timer.h b/base/timer/timer.h index 4ef2f45..7e2c1d4 100644 --- a/base/timer/timer.h +++ b/base/timer/timer.h @@ -60,6 +60,7 @@ namespace base { class BaseTimerTaskInternal; +class SingleThreadTaskRunner; //----------------------------------------------------------------------------- // This class wraps MessageLoop::PostDelayedTask to manage delayed and repeating @@ -87,6 +88,10 @@ class BASE_EXPORT Timer { // Returns the current delay for this timer. virtual TimeDelta GetCurrentDelay() const; + // Set the task runner on which the task should be scheduled. This method can + // only be called before any tasks have been scheduled. + virtual void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner); + // Start the timer to run at the given |delay| from now. If the timer is // already running, it will be replaced to call the given |user_task|. virtual void Start(const tracked_objects::Location& posted_from, @@ -128,6 +133,11 @@ class BASE_EXPORT Timer { // and desired_run_time_ are reset to Now() + delay. void PostNewScheduledTask(TimeDelta delay); + // Returns the task runner on which the task should be scheduled. If the + // corresponding task_runner_ field is null, the task runner for the current + // thread is returned. + scoped_refptr<SingleThreadTaskRunner> GetTaskRunner(); + // Disable scheduled_task_ and abandon it so that it no longer refers back to // this object. void AbandonScheduledTask(); @@ -145,6 +155,10 @@ class BASE_EXPORT Timer { // RunScheduledTask() at scheduled_run_time_. BaseTimerTaskInternal* scheduled_task_; + // The task runner on which the task should be scheduled. If it is null, the + // task runner for the current thread should be used. + scoped_refptr<SingleThreadTaskRunner> task_runner_; + // Location in user code. tracked_objects::Location posted_from_; // Delay requested by user. diff --git a/base/timer/timer_unittest.cc b/base/timer/timer_unittest.cc index 0fb2b45..1cbccd1 100644 --- a/base/timer/timer_unittest.cc +++ b/base/timer/timer_unittest.cc @@ -4,10 +4,12 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/test/test_simple_task_runner.h" #include "base/timer/timer.h" #include "testing/gtest/include/gtest/gtest.h" using base::TimeDelta; +using base::SingleThreadTaskRunner; namespace { @@ -26,20 +28,32 @@ class OneShotTimerTester { public: explicit OneShotTimerTester(bool* did_run, unsigned milliseconds = 10) : did_run_(did_run), - delay_ms_(milliseconds) { + delay_ms_(milliseconds), + quit_message_loop_(true) { } + void Start() { timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(delay_ms_), this, &OneShotTimerTester::Run); } + + void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner) { + quit_message_loop_ = false; + timer_.SetTaskRunner(task_runner); + } + private: void Run() { *did_run_ = true; - base::MessageLoop::current()->QuitWhenIdle(); + if (quit_message_loop_) { + base::MessageLoop::current()->QuitWhenIdle(); + } } + bool* did_run_; base::OneShotTimer<OneShotTimerTester> timer_; const unsigned delay_ms_; + bool quit_message_loop_; }; class OneShotSelfDeletingTimerTester { @@ -48,16 +62,19 @@ class OneShotSelfDeletingTimerTester { did_run_(did_run), timer_(new base::OneShotTimer<OneShotSelfDeletingTimerTester>()) { } + void Start() { timer_->Start(FROM_HERE, TimeDelta::FromMilliseconds(10), this, &OneShotSelfDeletingTimerTester::Run); } + private: void Run() { *did_run_ = true; timer_.reset(); base::MessageLoop::current()->QuitWhenIdle(); } + bool* did_run_; scoped_ptr<base::OneShotTimer<OneShotSelfDeletingTimerTester> > timer_; }; @@ -71,6 +88,7 @@ class RepeatingTimerTester { void Start() { timer_.Start(FROM_HERE, delay_, this, &RepeatingTimerTester::Run); } + private: void Run() { if (--counter_ == 0) { @@ -79,6 +97,7 @@ class RepeatingTimerTester { base::MessageLoop::current()->QuitWhenIdle(); } } + bool* did_run_; int counter_; TimeDelta delay_; @@ -310,6 +329,20 @@ TEST(TimerTest, OneShotSelfDeletingTimer) { } } +TEST(TimerTest, OneShotTimer_CustomTaskRunner) { + scoped_refptr<base::TestSimpleTaskRunner> task_runner = + new base::TestSimpleTaskRunner(); + + bool did_run = false; + OneShotTimerTester f(&did_run); + f.SetTaskRunner(task_runner); + f.Start(); + + EXPECT_FALSE(did_run); + task_runner->RunUntilIdle(); + EXPECT_TRUE(did_run); +} + TEST(TimerTest, RepeatingTimer) { for (int i = 0; i < kNumTestingMessageLoops; i++) { RunTest_RepeatingTimer(testing_message_loops[i], |