summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorpetrcermak <petrcermak@chromium.org>2014-11-05 18:17:57 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-06 02:18:21 +0000
commit7652da6d5cbd7e5b82b340e638ebe80aafeacf6e (patch)
tree25110fc030ba4aa5d0b1c3e1ca14c62e2b6b4acd /base
parentcac4fcac08708216009373121e573686adaac869 (diff)
downloadchromium_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.cc14
-rw-r--r--base/timer/timer.h14
-rw-r--r--base/timer/timer_unittest.cc37
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],