Commit f3336c9f authored by tzik's avatar tzik Committed by Commit Bot

Support base::OnceCallback on base::OneShotTimer

This moves task management logic of base::internal::TimerBase to its
subclasses, so that subclasses can hold user tasks as different types
for each.
Specifically, OneShotTimer's task type is converted to OnceClosure after
this CL, and it gets supporting OnceCallback.

Bug: 850247
Change-Id: Ie017c2ed6e0fb1fe44937a497576d16e5c3dab68
Reviewed-on: https://chromium-review.googlesource.com/1127215Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Commit-Queue: Taiju Tsuiki <tzik@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577784}
parent cf14c745
......@@ -58,17 +58,10 @@ class BaseTimerTaskInternal {
DISALLOW_COPY_AND_ASSIGN(BaseTimerTaskInternal);
};
TimerBase::TimerBase(bool retain_user_task, bool is_repeating)
: TimerBase(retain_user_task, is_repeating, nullptr) {}
TimerBase::TimerBase() : TimerBase(nullptr) {}
TimerBase::TimerBase(bool retain_user_task,
bool is_repeating,
const TickClock* tick_clock)
: scheduled_task_(nullptr),
is_repeating_(is_repeating),
retain_user_task_(retain_user_task),
tick_clock_(tick_clock),
is_running_(false) {
TimerBase::TimerBase(const TickClock* tick_clock)
: scheduled_task_(nullptr), tick_clock_(tick_clock), is_running_(false) {
// It is safe for the timer to be created on a different thread/sequence than
// the one from which the timer APIs are called. The first call to the
// checker's CalledOnValidSequence() method will re-bind the checker, and
......@@ -76,23 +69,15 @@ TimerBase::TimerBase(bool retain_user_task,
origin_sequence_checker_.DetachFromSequence();
}
TimerBase::TimerBase(const Location& posted_from,
TimeDelta delay,
const base::Closure& user_task,
bool is_repeating)
: TimerBase(posted_from, delay, user_task, is_repeating, nullptr) {}
TimerBase::TimerBase(const Location& posted_from, TimeDelta delay)
: TimerBase(posted_from, delay, nullptr) {}
TimerBase::TimerBase(const Location& posted_from,
TimeDelta delay,
const base::Closure& user_task,
bool is_repeating,
const TickClock* tick_clock)
: scheduled_task_(nullptr),
posted_from_(posted_from),
delay_(delay),
user_task_(user_task),
is_repeating_(is_repeating),
retain_user_task_(true),
tick_clock_(tick_clock),
is_running_(false) {
// See comment in other constructor.
......@@ -101,7 +86,7 @@ TimerBase::TimerBase(const Location& posted_from,
TimerBase::~TimerBase() {
DCHECK(origin_sequence_checker_.CalledOnValidSequence());
AbandonAndStop();
AbandonScheduledTask();
}
bool TimerBase::IsRunning() const {
......@@ -126,14 +111,11 @@ void TimerBase::SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) {
task_runner_.swap(task_runner);
}
void TimerBase::Start(const Location& posted_from,
TimeDelta delay,
const base::Closure& user_task) {
void TimerBase::StartInternal(const Location& posted_from, TimeDelta delay) {
DCHECK(origin_sequence_checker_.CalledOnValidSequence());
posted_from_ = posted_from;
delay_ = delay;
user_task_ = user_task;
Reset();
}
......@@ -148,15 +130,12 @@ void TimerBase::Stop() {
// It's safe to destroy or restart Timer on another sequence after Stop().
origin_sequence_checker_.DetachFromSequence();
if (!retain_user_task_)
user_task_.Reset();
// No more member accesses here: |this| could be deleted after freeing
// |user_task_|.
OnStop();
// No more member accesses here: |this| could be deleted after Stop() call.
}
void TimerBase::Reset() {
DCHECK(origin_sequence_checker_.CalledOnValidSequence());
DCHECK(!user_task_.is_null());
// If there's no pending task, start one up and return.
if (!scheduled_task_) {
......@@ -201,14 +180,12 @@ void TimerBase::PostNewScheduledTask(TimeDelta delay) {
// this code racy. https://crbug.com/587199
GetTaskRunner()->PostDelayedTask(
posted_from_,
base::BindOnce(&BaseTimerTaskInternal::Run,
base::Owned(scheduled_task_)),
delay);
BindOnce(&BaseTimerTaskInternal::Run, Owned(scheduled_task_)), delay);
scheduled_run_time_ = desired_run_time_ = Now() + delay;
} else {
GetTaskRunner()->PostTask(posted_from_,
base::BindOnce(&BaseTimerTaskInternal::Run,
base::Owned(scheduled_task_)));
GetTaskRunner()->PostTask(
posted_from_,
BindOnce(&BaseTimerTaskInternal::Run, Owned(scheduled_task_)));
scheduled_run_time_ = desired_run_time_ = TimeTicks();
}
}
......@@ -250,31 +227,114 @@ void TimerBase::RunScheduledTask() {
}
}
// Make a local copy of the task to run. The Stop method will reset the
// |user_task_| member if |retain_user_task_| is false.
base::Closure task = user_task_;
if (is_repeating_)
PostNewScheduledTask(delay_);
else
Stop();
task.Run();
RunUserTask();
// No more member accesses here: |this| could be deleted at this point.
}
} // namespace internal
OneShotTimer::OneShotTimer() = default;
OneShotTimer::OneShotTimer(const TickClock* tick_clock)
: internal::TimerBase(tick_clock) {}
OneShotTimer::~OneShotTimer() = default;
void OneShotTimer::Start(const Location& posted_from,
TimeDelta delay,
OnceClosure user_task) {
user_task_ = std::move(user_task);
StartInternal(posted_from, delay);
}
void OneShotTimer::FireNow() {
DCHECK(origin_sequence_checker_.CalledOnValidSequence());
DCHECK(!task_runner_) << "FireNow() is incompatible with SetTaskRunner()";
DCHECK(IsRunning());
OnceClosure task = user_task();
RunUserTask();
}
void OneShotTimer::OnStop() {
user_task_.Reset();
// No more member accesses here: |this| could be deleted after freeing
// |user_task_|.
}
void OneShotTimer::RunUserTask() {
// Make a local copy of the task to run. The Stop method will reset the
// |user_task_| member.
OnceClosure task = std::move(user_task_);
Stop();
DCHECK(!user_task());
DCHECK(task);
std::move(task).Run();
// No more member accesses here: |this| could be deleted at this point.
}
RepeatingTimer::RepeatingTimer() = default;
RepeatingTimer::RepeatingTimer(const TickClock* tick_clock)
: internal::TimerBase(tick_clock) {}
RepeatingTimer::~RepeatingTimer() = default;
RepeatingTimer::RepeatingTimer(const Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task)
: internal::TimerBase(posted_from, delay),
user_task_(std::move(user_task)) {}
RepeatingTimer::RepeatingTimer(const Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task,
const TickClock* tick_clock)
: internal::TimerBase(posted_from, delay, tick_clock),
user_task_(std::move(user_task)) {}
void RepeatingTimer::Start(const Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task) {
user_task_ = std::move(user_task);
StartInternal(posted_from, delay);
}
void RepeatingTimer::OnStop() {}
void RepeatingTimer::RunUserTask() {
// Make a local copy of the task to run in case the task destroy the timer
// instance.
RepeatingClosure task = user_task_;
PostNewScheduledTask(GetCurrentDelay());
task.Run();
// No more member accesses here: |this| could be deleted at this point.
}
RetainingOneShotTimer::RetainingOneShotTimer() = default;
RetainingOneShotTimer::RetainingOneShotTimer(const TickClock* tick_clock)
: internal::TimerBase(tick_clock) {}
RetainingOneShotTimer::~RetainingOneShotTimer() = default;
RetainingOneShotTimer::RetainingOneShotTimer(const Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task)
: internal::TimerBase(posted_from, delay),
user_task_(std::move(user_task)) {}
RetainingOneShotTimer::RetainingOneShotTimer(const Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task,
const TickClock* tick_clock)
: internal::TimerBase(posted_from, delay, tick_clock),
user_task_(std::move(user_task)) {}
void RetainingOneShotTimer::Start(const Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task) {
user_task_ = std::move(user_task);
StartInternal(posted_from, delay);
}
void RetainingOneShotTimer::OnStop() {}
void RetainingOneShotTimer::RunUserTask() {
// Make a local copy of the task to run in case the task destroys the timer
// instance.
RepeatingClosure task = user_task_;
Stop();
task.Run();
// No more member accesses here: |this| could be deleted at this point.
}
} // namespace base
......@@ -92,25 +92,18 @@ class BaseTimerTaskInternal;
//
class BASE_EXPORT TimerBase {
public:
// Construct a timer in repeating or one-shot mode. Start must be called later
// to set task info. |retain_user_task| determines whether the user_task is
// retained or reset when it runs or stops. If |tick_clock| is provided, it is
// used instead of TimeTicks::Now() to get TimeTicks when scheduling tasks.
TimerBase(bool retain_user_task, bool is_repeating);
TimerBase(bool retain_user_task,
bool is_repeating,
const TickClock* tick_clock);
// Construct a timer with retained task info. If |tick_clock| is provided, it
// is used instead of TimeTicks::Now() to get TimeTicks when scheduling tasks.
TimerBase(const Location& posted_from,
TimeDelta delay,
const base::Closure& user_task,
bool is_repeating);
// Constructs a timer. Start must be called later to set task info.
// If |tick_clock| is provided, it is used instead of TimeTicks::Now() to get
// TimeTicks when scheduling tasks.
TimerBase();
explicit TimerBase(const TickClock* tick_clock);
// Construct a timer with task info.
// If |tick_clock| is provided, it is used instead of TimeTicks::Now() to get
// TimeTicks when scheduling tasks.
TimerBase(const Location& posted_from, TimeDelta delay);
TimerBase(const Location& posted_from,
TimeDelta delay,
const base::Closure& user_task,
bool is_repeating,
const TickClock* tick_clock);
virtual ~TimerBase();
......@@ -123,29 +116,11 @@ class BASE_EXPORT TimerBase {
// Set the task runner on which the task should be scheduled. This method can
// only be called before any tasks have been scheduled. If |task_runner| runs
// tasks on a different sequence than the sequence owning this Timer,
// |user_task_| will be posted to it when the Timer fires (note that this
// means |user_task_| can run after ~Timer() and should support that).
// tasks on a different sequence than the sequence owning this Timer, the user
// task will be posted to it when the Timer fires (note that this means the
// user task can run after ~Timer() and should support that).
virtual void SetTaskRunner(scoped_refptr<SequencedTaskRunner> 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 Location& posted_from,
TimeDelta delay,
const base::Closure& user_task);
// Start the timer to run at the given |delay| from now. If the timer is
// already running, it will be replaced to call a task formed from
// |reviewer->*method|.
template <class Receiver>
void Start(const Location& posted_from,
TimeDelta delay,
Receiver* receiver,
void (Receiver::*method)()) {
Start(posted_from, delay,
base::BindRepeating(method, base::Unretained(receiver)));
}
// Call this method to stop and cancel the timer. It is a no-op if the timer
// is not running.
virtual void Stop();
......@@ -158,18 +133,19 @@ class BASE_EXPORT TimerBase {
// No more member accesses here: |this| could be deleted at this point.
}
// Call this method to reset the timer delay. The |user_task_| must be set. If
// Call this method to reset the timer delay. The user task must be set. If
// the timer is not running, this will start it by posting a task.
virtual void Reset();
const base::Closure& user_task() const { return user_task_; }
const TimeTicks& desired_run_time() const { return desired_run_time_; }
protected:
virtual void OnStop() = 0;
virtual void RunUserTask() = 0;
// Returns the current tick count.
TimeTicks Now() const;
void set_user_task(const Closure& task) { user_task_ = task; }
void set_desired_run_time(TimeTicks desired) { desired_run_time_ = desired; }
void set_is_running(bool running) { is_running_ = running; }
......@@ -184,14 +160,16 @@ class BASE_EXPORT TimerBase {
// destroyed or restarted on another sequence.
SequenceChecker origin_sequence_checker_;
private:
friend class BaseTimerTaskInternal;
// Allocates a new |scheduled_task_| and posts it on the current sequence with
// the given |delay|. |scheduled_task_| must be null. |scheduled_run_time_|
// and |desired_run_time_| are reset to Now() + delay.
void PostNewScheduledTask(TimeDelta delay);
void StartInternal(const Location& posted_from, TimeDelta delay);
private:
friend class BaseTimerTaskInternal;
// 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
// sequence is returned.
......@@ -212,8 +190,6 @@ class BASE_EXPORT TimerBase {
Location posted_from_;
// Delay requested by user.
TimeDelta delay_;
// |user_task_| is what the user wants to be run at |desired_run_time_|.
base::Closure user_task_;
// The time at which |scheduled_task_| is expected to fire. This time can be a
// "zero" TimeTicks if the task must be run immediately.
......@@ -228,13 +204,6 @@ class BASE_EXPORT TimerBase {
// if the task must be run immediately.
TimeTicks desired_run_time_;
// Repeating timers automatically post the task again before calling the task
// callback.
const bool is_repeating_;
// If true, hold on to the |user_task_| closure object for reuse.
const bool retain_user_task_;
// The tick clock used to calculate the run time for scheduled tasks.
const TickClock* const tick_clock_;
......@@ -250,60 +219,134 @@ class BASE_EXPORT TimerBase {
// A simple, one-shot timer. See usage notes at the top of the file.
class BASE_EXPORT OneShotTimer : public internal::TimerBase {
public:
OneShotTimer() : OneShotTimer(nullptr) {}
explicit OneShotTimer(const TickClock* tick_clock)
: internal::TimerBase(false, false, tick_clock) {}
OneShotTimer();
explicit OneShotTimer(const TickClock* tick_clock);
~OneShotTimer() override;
// 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 Location& posted_from,
TimeDelta delay,
OnceClosure user_task);
// Start the timer to run at the given |delay| from now. If the timer is
// already running, it will be replaced to call a task formed from
// |reviewer->*method|.
template <class Receiver>
void Start(const Location& posted_from,
TimeDelta delay,
Receiver* receiver,
void (Receiver::*method)()) {
Start(posted_from, delay, BindOnce(method, Unretained(receiver)));
}
// Run the scheduled task immediately, and stop the timer. The timer needs to
// be running.
void FireNow();
private:
void OnStop() final;
void RunUserTask() final;
OnceClosure user_task_;
DISALLOW_COPY_AND_ASSIGN(OneShotTimer);
};
//-----------------------------------------------------------------------------
// A simple, repeating timer. See usage notes at the top of the file.
class RepeatingTimer : public internal::TimerBase {
class BASE_EXPORT RepeatingTimer : public internal::TimerBase {
public:
RepeatingTimer() : RepeatingTimer(nullptr) {}
explicit RepeatingTimer(const TickClock* tick_clock)
: internal::TimerBase(true, true, tick_clock) {}
RepeatingTimer();
explicit RepeatingTimer(const TickClock* tick_clock);
~RepeatingTimer() override;
RepeatingTimer(const Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task)
: internal::TimerBase(posted_from, delay, std::move(user_task), true) {}
RepeatingClosure user_task);
RepeatingTimer(const Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task,
const TickClock* tick_clock)
: internal::TimerBase(posted_from,
delay,
std::move(user_task),
true,
tick_clock) {}
const TickClock* tick_clock);
// 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 Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task);
// Start the timer to run at the given |delay| from now. If the timer is
// already running, it will be replaced to call a task formed from
// |reviewer->*method|.
template <class Receiver>
void Start(const Location& posted_from,
TimeDelta delay,
Receiver* receiver,
void (Receiver::*method)()) {
Start(posted_from, delay, BindRepeating(method, Unretained(receiver)));
}
const RepeatingClosure& user_task() const { return user_task_; }
private:
// Mark this final, so that the destructor can call this safely.
void OnStop() final;
void RunUserTask() override;
RepeatingClosure user_task_;
DISALLOW_COPY_AND_ASSIGN(RepeatingTimer);
};
//-----------------------------------------------------------------------------
// A simple, one-shot timer with the retained user task. See usage notes at the
// top of the file.
class RetainingOneShotTimer : public internal::TimerBase {
class BASE_EXPORT RetainingOneShotTimer : public internal::TimerBase {
public:
RetainingOneShotTimer() : RetainingOneShotTimer(nullptr) {}
explicit RetainingOneShotTimer(const TickClock* tick_clock)
: internal::TimerBase(true, false, tick_clock) {}
RetainingOneShotTimer();
explicit RetainingOneShotTimer(const TickClock* tick_clock);
~RetainingOneShotTimer() override;
RetainingOneShotTimer(const Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task)
: internal::TimerBase(posted_from, delay, std::move(user_task), false) {}
RepeatingClosure user_task);
RetainingOneShotTimer(const Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task,
const TickClock* tick_clock)
: internal::TimerBase(posted_from,
delay,
std::move(user_task),
false,
tick_clock) {}
const TickClock* tick_clock);
// 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 Location& posted_from,
TimeDelta delay,
RepeatingClosure user_task);
// Start the timer to run at the given |delay| from now. If the timer is
// already running, it will be replaced to call a task formed from
// |reviewer->*method|.
template <class Receiver>
void Start(const Location& posted_from,
TimeDelta delay,
Receiver* receiver,
void (Receiver::*method)()) {
Start(posted_from, delay, BindRepeating(method, Unretained(receiver)));
}
const RepeatingClosure& user_task() const { return user_task_; }
protected:
void set_user_task(const RepeatingClosure& task) { user_task_ = task; }
private:
// Mark this final, so that the destructor can call this safely.
void OnStop() final;
void RunUserTask() override;
RepeatingClosure user_task_;
DISALLOW_COPY_AND_ASSIGN(RetainingOneShotTimer);
};
//-----------------------------------------------------------------------------
......
......@@ -112,7 +112,7 @@ class OneShotTimerTester : public OneShotTimerTesterBase {
// Run() will be invoked on |task_runner| but |run_loop_|'s QuitClosure
// needs to run on this thread (where the MessageLoop lives).
quit_closure_ = Bind(IgnoreResult(&SequencedTaskRunner::PostTask),
quit_closure_ = BindOnce(IgnoreResult(&SequencedTaskRunner::PostTask),
SequencedTaskRunnerHandle::Get(), FROM_HERE,
run_loop_.QuitClosure());
}
......@@ -135,11 +135,11 @@ class OneShotTimerTester : public OneShotTimerTesterBase {
void Run() override {
OnRun();
OneShotTimerTesterBase::Run();
quit_closure_.Run();
std::move(quit_closure_).Run();
}
RunLoop run_loop_;
Closure quit_closure_;
OnceClosure quit_closure_;
DISALLOW_COPY_AND_ASSIGN(OneShotTimerTester);
};
......@@ -440,7 +440,7 @@ TEST(TimerTest, OneShotTimerWithTickClock) {
Receiver receiver;
OneShotTimer timer(task_runner->GetMockTickClock());
timer.Start(FROM_HERE, TimeDelta::FromSeconds(1),
Bind(&Receiver::OnCalled, Unretained(&receiver)));
BindOnce(&Receiver::OnCalled, Unretained(&receiver)));
task_runner->FastForwardBy(TimeDelta::FromSeconds(1));
EXPECT_TRUE(receiver.WasCalled());
}
......@@ -482,7 +482,7 @@ TEST(TimerTest, RepeatingTimerWithTickClock) {
const int expected_times_called = 10;
RepeatingTimer timer(task_runner->GetMockTickClock());
timer.Start(FROM_HERE, TimeDelta::FromSeconds(1),
Bind(&Receiver::OnCalled, Unretained(&receiver)));
BindRepeating(&Receiver::OnCalled, Unretained(&receiver)));
task_runner->FastForwardBy(TimeDelta::FromSeconds(expected_times_called));
timer.Stop();
EXPECT_EQ(expected_times_called, receiver.TimesCalled());
......@@ -565,7 +565,7 @@ class OneShotSelfOwningTimerTester
// Start timer with long delay in order to test the timer getting destroyed
// while a timer task is still pending.
timer_.Start(FROM_HERE, TimeDelta::FromDays(1),
base::Bind(&OneShotSelfOwningTimerTester::Run, this));
BindOnce(&OneShotSelfOwningTimerTester::Run, this));
}
private:
......@@ -605,18 +605,19 @@ TEST(TimerTest, NonRepeatIsRunning) {
MessageLoop loop;
OneShotTimer timer;
EXPECT_FALSE(timer.IsRunning());
timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
timer.Start(FROM_HERE, TimeDelta::FromDays(1),
BindOnce(&TimerTestCallback));
EXPECT_TRUE(timer.IsRunning());
timer.Stop();
EXPECT_FALSE(timer.IsRunning());
EXPECT_TRUE(timer.user_task().is_null());
}
{
RetainingOneShotTimer timer;
MessageLoop loop;
EXPECT_FALSE(timer.IsRunning());
timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
timer.Start(FROM_HERE, TimeDelta::FromDays(1),
BindRepeating(&TimerTestCallback));
EXPECT_TRUE(timer.IsRunning());
timer.Stop();
EXPECT_FALSE(timer.IsRunning());
......@@ -631,17 +632,17 @@ TEST(TimerTest, NonRepeatMessageLoopDeath) {
{
MessageLoop loop;
EXPECT_FALSE(timer.IsRunning());
timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
timer.Start(FROM_HERE, TimeDelta::FromDays(1),
BindOnce(&TimerTestCallback));
EXPECT_TRUE(timer.IsRunning());
}
EXPECT_FALSE(timer.IsRunning());
EXPECT_TRUE(timer.user_task().is_null());
}
TEST(TimerTest, RetainRepeatIsRunning) {
MessageLoop loop;
RepeatingTimer timer(FROM_HERE, TimeDelta::FromDays(1),
Bind(&TimerTestCallback));
BindRepeating(&TimerTestCallback));
EXPECT_FALSE(timer.IsRunning());
timer.Reset();
EXPECT_TRUE(timer.IsRunning());
......@@ -654,7 +655,7 @@ TEST(TimerTest, RetainRepeatIsRunning) {
TEST(TimerTest, RetainNonRepeatIsRunning) {
MessageLoop loop;
RetainingOneShotTimer timer(FROM_HERE, TimeDelta::FromDays(1),
Bind(&TimerTestCallback));
BindRepeating(&TimerTestCallback));
EXPECT_FALSE(timer.IsRunning());
timer.Reset();
EXPECT_TRUE(timer.IsRunning());
......@@ -694,10 +695,10 @@ TEST(TimerTest, ContinuationStopStart) {
MessageLoop loop;
OneShotTimer timer;
timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
Bind(&SetCallbackHappened1));
BindOnce(&SetCallbackHappened1));
timer.Stop();
timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(40),
Bind(&SetCallbackHappened2));
BindOnce(&SetCallbackHappened2));
RunLoop().Run();
EXPECT_FALSE(g_callback_happened1);
EXPECT_TRUE(g_callback_happened2);
......@@ -710,10 +711,10 @@ TEST(TimerTest, ContinuationReset) {
MessageLoop loop;
OneShotTimer timer;
timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
Bind(&SetCallbackHappened1));
BindOnce(&SetCallbackHappened1));
timer.Reset();
// Since Reset happened before task ran, the user_task must not be cleared:
ASSERT_FALSE(timer.user_task().is_null());
// // Since Reset happened before task ran, the user_task must not be
// cleared: ASSERT_FALSE(timer.user_task().is_null());
RunLoop().Run();
EXPECT_TRUE(g_callback_happened1);
}
......@@ -736,16 +737,17 @@ class TimerSequenceTest : public testing::Test {
void Signal() { event_.Signal(); }
// Helper to augment a task with a subsequent call to Signal().
Closure TaskWithSignal(const Closure& task) {
return Bind(&TimerSequenceTest::RunTaskAndSignal, Unretained(this), task);
OnceClosure TaskWithSignal(OnceClosure task) {
return BindOnce(&TimerSequenceTest::RunTaskAndSignal, Unretained(this),
std::move(task));
}
// Create the timer.
void CreateTimer() { timer_.reset(new OneShotTimer); }
// Schedule an event on the timer.
void StartTimer(TimeDelta delay, const Closure& task) {
timer_->Start(FROM_HERE, delay, task);
void StartTimer(TimeDelta delay, OnceClosure task) {
timer_->Start(FROM_HERE, delay, std::move(task));
}
void SetTaskRunnerForTimer(scoped_refptr<SequencedTaskRunner> task_runner) {
......@@ -770,8 +772,8 @@ class TimerSequenceTest : public testing::Test {
void DeleteTimer() { timer_.reset(); }
private:
void RunTaskAndSignal(const Closure& task) {
task.Run();
void RunTaskAndSignal(OnceClosure task) {
std::move(task).Run();
Signal();
}
......@@ -796,7 +798,7 @@ TEST_F(TimerSequenceTest, OneShotTimerTaskOnPoolSequence) {
// Task will execute on a pool thread.
SetTaskRunnerForTimer(task_runner);
StartTimer(TimeDelta::FromMilliseconds(1),
Bind(IgnoreResult(&SequencedTaskRunner::PostTask),
BindOnce(IgnoreResult(&SequencedTaskRunner::PostTask),
SequencedTaskRunnerHandle::Get(), FROM_HERE,
run_loop_.QuitClosure()));
......@@ -818,15 +820,16 @@ TEST_F(TimerSequenceTest, OneShotTimerUsedOnPoolSequence) {
// Task will be scheduled from a pool thread.
task_runner->PostTask(
FROM_HERE, BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
FROM_HERE,
BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
TimeDelta::FromMilliseconds(1),
Bind(&TimerSequenceTest::Signal, Unretained(this))));
BindOnce(&TimerSequenceTest::Signal, Unretained(this))));
Wait();
// Timer must be destroyed on pool thread, too.
task_runner->PostTask(
FROM_HERE,
TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
task_runner->PostTask(FROM_HERE,
TaskWithSignal(BindOnce(&TimerSequenceTest::DeleteTimer,
Unretained(this))));
Wait();
}
......@@ -838,31 +841,32 @@ TEST_F(TimerSequenceTest, OneShotTimerTwoSequencesAbandonTask) {
// Create timer on sequence #1.
task_runner1->PostTask(
FROM_HERE,
TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
FROM_HERE, TaskWithSignal(BindOnce(&TimerSequenceTest::CreateTimer,
Unretained(this))));
Wait();
// And tell it to execute on a different sequence (#2).
task_runner1->PostTask(
FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
FROM_HERE,
TaskWithSignal(BindOnce(&TimerSequenceTest::SetTaskRunnerForTimer,
Unretained(this), task_runner2)));
Wait();
// Task will be scheduled from sequence #1.
task_runner1->PostTask(
FROM_HERE, BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
TimeDelta::FromHours(1), DoNothing()));
TimeDelta::FromHours(1), DoNothing().Once()));
// Abandon task - must be called from scheduling sequence (#1).
task_runner1->PostTask(
FROM_HERE,
TaskWithSignal(Bind(&TimerSequenceTest::AbandonTask, Unretained(this))));
FROM_HERE, TaskWithSignal(BindOnce(&TimerSequenceTest::AbandonTask,
Unretained(this))));
Wait();
// Timer must be destroyed on the sequence it was scheduled from (#1).
task_runner1->PostTask(
FROM_HERE,
TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
FROM_HERE, TaskWithSignal(BindOnce(&TimerSequenceTest::DeleteTimer,
Unretained(this))));
Wait();
}
......@@ -874,13 +878,14 @@ TEST_F(TimerSequenceTest, OneShotTimerUsedAndTaskedOnDifferentSequences) {
// Create timer on sequence #1.
task_runner1->PostTask(
FROM_HERE,
TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
FROM_HERE, TaskWithSignal(BindOnce(&TimerSequenceTest::CreateTimer,
Unretained(this))));
Wait();
// And tell it to execute on a different sequence (#2).
task_runner1->PostTask(
FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
FROM_HERE,
TaskWithSignal(BindOnce(&TimerSequenceTest::SetTaskRunnerForTimer,
Unretained(this), task_runner2)));
Wait();
......@@ -889,15 +894,15 @@ TEST_F(TimerSequenceTest, OneShotTimerUsedAndTaskedOnDifferentSequences) {
FROM_HERE,
BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
TimeDelta::FromMilliseconds(1),
TaskWithSignal(Bind(&TimerSequenceTest::VerifyAffinity,
TaskWithSignal(BindOnce(&TimerSequenceTest::VerifyAffinity,
Unretained(task_runner2.get())))));
Wait();
// Timer must be destroyed on the sequence it was scheduled from (#1).
task_runner1->PostTask(
FROM_HERE,
TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
FROM_HERE, TaskWithSignal(BindOnce(&TimerSequenceTest::DeleteTimer,
Unretained(this))));
Wait();
}
......
......@@ -381,17 +381,15 @@ class MockTimer : public base::MockOneShotTimer {
void Start(const base::Location& posted_from,
base::TimeDelta delay,
const base::Closure& user_task) override {
StartObserver(posted_from, delay, user_task);
base::MockOneShotTimer::Start(posted_from, delay, user_task);
base::OnceClosure user_task) override {
StartObserver(posted_from, delay);
base::MockOneShotTimer::Start(posted_from, delay, std::move(user_task));
}
// StartObserver is invoked when MockTimer::Start() is called.
// Does not replace the behavior of MockTimer::Start().
MOCK_METHOD3(StartObserver,
void(const base::Location& posted_from,
base::TimeDelta delay,
const base::Closure& user_task));
MOCK_METHOD2(StartObserver,
void(const base::Location& posted_from, base::TimeDelta delay));
private:
DISALLOW_COPY_AND_ASSIGN(MockTimer);
......@@ -565,7 +563,7 @@ TEST_F(MDnsTest, CacheCleanupWithShortTTL) {
test_client_.reset(new MDnsClientImpl(&clock, base::WrapUnique(timer)));
test_client_->StartListening(&socket_factory_);
EXPECT_CALL(*timer, StartObserver(_, _, _)).Times(1);
EXPECT_CALL(*timer, StartObserver(_, _)).Times(1);
EXPECT_CALL(clock, Now())
.Times(3)
.WillRepeatedly(Return(start_time))
......@@ -608,7 +606,7 @@ TEST_F(MDnsTest, CacheCleanupWithShortTTL) {
.WillOnce(Return(start_time + base::TimeDelta::FromSeconds(2)))
.RetiresOnSaturation();
EXPECT_CALL(*timer, StartObserver(_, base::TimeDelta(), _));
EXPECT_CALL(*timer, StartObserver(_, base::TimeDelta()));
timer->Fire();
}
......
......@@ -384,10 +384,11 @@ class MockTimer : public base::MockOneShotTimer {
void Start(const base::Location& posted_from,
base::TimeDelta delay,
const base::Closure& user_task) override {
base::OnceClosure user_task) override {
// Sets a maximum delay, so the timer does not fire unless it is told to.
base::TimeDelta infinite_delay = base::TimeDelta::Max();
base::MockOneShotTimer::Start(posted_from, infinite_delay, user_task);
base::MockOneShotTimer::Start(posted_from, infinite_delay,
std::move(user_task));
}
private:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment