Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 14:04:28 +01:00
parent 81b91f4139
commit f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions

View file

@ -0,0 +1,52 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/timer/elapsed_timer.h"
namespace base {
namespace {
bool g_mock_elapsed_timers_for_test = false;
} // namespace
ElapsedTimer::ElapsedTimer() : begin_(TimeTicks::Now()) {}
ElapsedTimer::ElapsedTimer(ElapsedTimer&& other) : begin_(other.begin_) {}
void ElapsedTimer::operator=(ElapsedTimer&& other) {
begin_ = other.begin_;
}
TimeDelta ElapsedTimer::Elapsed() const {
if (g_mock_elapsed_timers_for_test)
return ScopedMockElapsedTimersForTest::kMockElapsedTime;
return TimeTicks::Now() - begin_;
}
ElapsedThreadTimer::ElapsedThreadTimer()
: is_supported_(ThreadTicks::IsSupported()),
begin_(is_supported_ ? ThreadTicks::Now() : ThreadTicks()) {}
TimeDelta ElapsedThreadTimer::Elapsed() const {
if (!is_supported_)
return TimeDelta();
if (g_mock_elapsed_timers_for_test)
return ScopedMockElapsedTimersForTest::kMockElapsedTime;
return ThreadTicks::Now() - begin_;
}
// static
constexpr TimeDelta ScopedMockElapsedTimersForTest::kMockElapsedTime;
ScopedMockElapsedTimersForTest::ScopedMockElapsedTimersForTest() {
DCHECK(!g_mock_elapsed_timers_for_test);
g_mock_elapsed_timers_for_test = true;
}
ScopedMockElapsedTimersForTest::~ScopedMockElapsedTimersForTest() {
DCHECK(g_mock_elapsed_timers_for_test);
g_mock_elapsed_timers_for_test = false;
}
} // namespace base

View file

@ -0,0 +1,73 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TIMER_ELAPSED_TIMER_H_
#define BASE_TIMER_ELAPSED_TIMER_H_
#include "base/base_export.h"
#include "base/macros.h"
#include "base/time/time.h"
namespace base {
// A simple wrapper around TimeTicks::Now().
class BASE_EXPORT ElapsedTimer {
public:
ElapsedTimer();
ElapsedTimer(ElapsedTimer&& other);
void operator=(ElapsedTimer&& other);
// Returns the time elapsed since object construction.
TimeDelta Elapsed() const;
// Returns the timestamp of the creation of this timer.
TimeTicks Begin() const { return begin_; }
private:
TimeTicks begin_;
DISALLOW_COPY_AND_ASSIGN(ElapsedTimer);
};
// A simple wrapper around ThreadTicks::Now().
class BASE_EXPORT ElapsedThreadTimer {
public:
ElapsedThreadTimer();
// Returns the ThreadTicks time elapsed since object construction.
// Only valid if |is_supported()| returns true, otherwise returns TimeDelta().
TimeDelta Elapsed() const;
bool is_supported() const { return is_supported_; }
private:
const bool is_supported_;
const ThreadTicks begin_;
DISALLOW_COPY_AND_ASSIGN(ElapsedThreadTimer);
};
// Whenever there's a ScopedMockElapsedTimersForTest in scope,
// Elapsed(Thread)Timers will always return kMockElapsedTime from Elapsed().
// This is useful, for example, in unit tests that verify that their impl
// records timing histograms. It enables such tests to observe reliable timings.
class BASE_EXPORT ScopedMockElapsedTimersForTest {
public:
static constexpr TimeDelta kMockElapsedTime =
TimeDelta::FromMilliseconds(1337);
// ScopedMockElapsedTimersForTest is not thread-safe (it must be instantiated
// in a test before other threads begin using ElapsedTimers; and it must
// conversely outlive any usage of ElapsedTimer in that test).
ScopedMockElapsedTimersForTest();
~ScopedMockElapsedTimersForTest();
private:
DISALLOW_COPY_AND_ASSIGN(ScopedMockElapsedTimersForTest);
};
} // namespace base
#endif // BASE_TIMER_ELAPSED_TIMER_H_

View file

@ -0,0 +1,48 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TIMER_HI_RES_TIMER_MANAGER_H_
#define BASE_TIMER_HI_RES_TIMER_MANAGER_H_
#include "base/base_export.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/power_monitor/power_observer.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
namespace base {
// Ensures that the Windows high resolution timer is only used
// when not running on battery power.
class BASE_EXPORT HighResolutionTimerManager : public base::PowerObserver {
public:
HighResolutionTimerManager();
~HighResolutionTimerManager() override;
// base::PowerObserver methods.
void OnPowerStateChange(bool on_battery_power) override;
void OnSuspend() override;
void OnResume() override;
// Returns true if the hi resolution clock could be used right now.
bool hi_res_clock_available() const { return hi_res_clock_available_; }
private:
// Enable or disable the faster multimedia timer.
void UseHiResClock(bool use);
bool hi_res_clock_available_;
#if defined(OS_WIN)
// Timer for polling the high resolution timer usage.
base::RepeatingTimer timer_;
#endif
DISALLOW_COPY_AND_ASSIGN(HighResolutionTimerManager);
};
} // namespace base
#endif // BASE_TIMER_HI_RES_TIMER_MANAGER_H_

View file

@ -0,0 +1,27 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/timer/hi_res_timer_manager.h"
// On POSIX we don't need to do anything special with the system timer.
namespace base {
HighResolutionTimerManager::HighResolutionTimerManager()
: hi_res_clock_available_(false) {
}
HighResolutionTimerManager::~HighResolutionTimerManager() = default;
void HighResolutionTimerManager::OnPowerStateChange(bool on_battery_power) {
}
void HighResolutionTimerManager::OnSuspend() {}
void HighResolutionTimerManager::OnResume() {}
void HighResolutionTimerManager::UseHiResClock(bool use) {
}
} // namespace base

View file

@ -0,0 +1,88 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/timer/hi_res_timer_manager.h"
#include <algorithm>
#include "base/atomicops.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
#include "base/power_monitor/power_monitor.h"
#include "base/task/post_task.h"
#include "base/time/time.h"
namespace base {
namespace {
constexpr TimeDelta kUsageSampleInterval = TimeDelta::FromMinutes(10);
void ReportHighResolutionTimerUsage() {
UMA_HISTOGRAM_PERCENTAGE("Windows.HighResolutionTimerUsage",
Time::GetHighResolutionTimerUsage());
// Reset usage for the next interval.
Time::ResetHighResolutionTimerUsage();
}
bool HighResolutionTimerAllowed() {
return !CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableHighResTimer);
}
} // namespace
HighResolutionTimerManager::HighResolutionTimerManager()
: hi_res_clock_available_(false) {
// Register for PowerMonitor callbacks only if high-resolution
// timers are allowed. If high-resolution timers are disabled
// we won't receive power state change callbacks and
// hi_res_clock_available_ will remain at its initial value.
if (HighResolutionTimerAllowed()) {
DCHECK(PowerMonitor::IsInitialized());
PowerMonitor::AddObserver(this);
UseHiResClock(!PowerMonitor::IsOnBatteryPower());
// Start polling the high resolution timer usage.
Time::ResetHighResolutionTimerUsage();
timer_.Start(FROM_HERE, kUsageSampleInterval,
BindRepeating(&ReportHighResolutionTimerUsage));
}
}
HighResolutionTimerManager::~HighResolutionTimerManager() {
if (HighResolutionTimerAllowed()) {
PowerMonitor::RemoveObserver(this);
UseHiResClock(false);
}
}
void HighResolutionTimerManager::OnPowerStateChange(bool on_battery_power) {
DCHECK(HighResolutionTimerAllowed());
UseHiResClock(!on_battery_power);
}
void HighResolutionTimerManager::OnSuspend() {
DCHECK(HighResolutionTimerAllowed());
// Stop polling the usage to avoid including the standby time.
timer_.Stop();
}
void HighResolutionTimerManager::OnResume() {
DCHECK(HighResolutionTimerAllowed());
// Resume polling the usage.
Time::ResetHighResolutionTimerUsage();
timer_.Reset();
}
void HighResolutionTimerManager::UseHiResClock(bool use) {
DCHECK(HighResolutionTimerAllowed());
if (use == hi_res_clock_available_)
return;
hi_res_clock_available_ = use;
Time::EnableHighResolutionTimer(use);
}
} // namespace base

View file

@ -0,0 +1,118 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/timer/lap_timer.h"
#include "base/logging.h"
namespace base {
namespace {
// Default values.
constexpr TimeDelta kDefaultTimeLimit = TimeDelta::FromSeconds(3);
constexpr int kDefaultWarmupRuns = 5;
constexpr int kDefaultTimeCheckInterval = 10;
} // namespace
LapTimer::LapTimer(int warmup_laps,
TimeDelta time_limit,
int check_interval,
LapTimer::TimerMethod method)
: warmup_laps_(warmup_laps),
time_limit_(time_limit),
check_interval_(check_interval),
method_(method) {
DETACH_FROM_SEQUENCE(sequence_checker_);
DCHECK_GT(check_interval, 0);
Reset();
}
LapTimer::LapTimer(LapTimer::TimerMethod method)
: LapTimer(kDefaultWarmupRuns,
kDefaultTimeLimit,
kDefaultTimeCheckInterval,
method) {}
void LapTimer::Reset() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (ThreadTicks::IsSupported() && method_ == TimerMethod::kUseThreadTicks)
ThreadTicks::WaitUntilInitialized();
num_laps_ = 0;
remaining_warmups_ = warmup_laps_;
remaining_no_check_laps_ = check_interval_;
Start();
}
void LapTimer::Start() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(num_laps_, 0);
// last_timed_ variables are initialized here (instead of in the constructor)
// because not all platforms support ThreadTicks.
if (method_ == TimerMethod::kUseThreadTicks) {
start_thread_ticks_ = ThreadTicks::Now();
last_timed_lap_end_thread_ticks_ = ThreadTicks::Now();
} else {
start_time_ticks_ = TimeTicks::Now();
last_timed_lap_end_ticks_ = TimeTicks::Now();
}
}
bool LapTimer::IsWarmedUp() const {
return remaining_warmups_ <= 0;
}
void LapTimer::NextLap() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!start_thread_ticks_.is_null() || !start_time_ticks_.is_null());
if (!IsWarmedUp()) {
--remaining_warmups_;
if (IsWarmedUp()) {
Start();
}
return;
}
++num_laps_;
--remaining_no_check_laps_;
if (!remaining_no_check_laps_) {
if (method_ == TimerMethod::kUseTimeTicks) {
last_timed_lap_end_ticks_ = TimeTicks::Now();
} else {
last_timed_lap_end_thread_ticks_ = ThreadTicks::Now();
}
remaining_no_check_laps_ = check_interval_;
}
}
TimeDelta LapTimer::GetAccumulatedTime() const {
if (method_ == TimerMethod::kUseTimeTicks) {
return last_timed_lap_end_ticks_ - start_time_ticks_;
}
return last_timed_lap_end_thread_ticks_ - start_thread_ticks_;
}
bool LapTimer::HasTimeLimitExpired() const {
return GetAccumulatedTime() >= time_limit_;
}
bool LapTimer::HasTimedAllLaps() const {
return num_laps_ && !(num_laps_ % check_interval_);
}
TimeDelta LapTimer::TimePerLap() const {
DCHECK(HasTimedAllLaps());
DCHECK_GT(num_laps_, 0);
return GetAccumulatedTime() / num_laps_;
}
float LapTimer::LapsPerSecond() const {
DCHECK(HasTimedAllLaps());
DCHECK_GT(num_laps_, 0);
return num_laps_ / GetAccumulatedTime().InSecondsF();
}
int LapTimer::NumLaps() const {
return num_laps_;
}
} // namespace base

View file

@ -0,0 +1,83 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/timer/mock_timer.h"
#include "base/test/test_simple_task_runner.h"
namespace base {
namespace {
void FlushPendingTasks(TestSimpleTaskRunner* task_runner) {
// Do not use TestSimpleTaskRunner::RunPendingTasks() here. As RunPendingTasks
// overrides ThreadTaskRunnerHandle when it runs tasks, tasks posted by timer
// tasks to TTRH go to |test_task_runner_|, though they should be posted to
// the original task runner.
// Do not use TestSimpleTaskRunner::RunPendingTasks(), as its overridden
// ThreadTaskRunnerHandle causes unexpected side effects.
for (TestPendingTask& task : task_runner->TakePendingTasks())
std::move(task.task).Run();
}
} // namespace
MockOneShotTimer::MockOneShotTimer()
: OneShotTimer(&clock_),
test_task_runner_(MakeRefCounted<TestSimpleTaskRunner>()) {
OneShotTimer::SetTaskRunner(test_task_runner_);
}
MockOneShotTimer::~MockOneShotTimer() = default;
void MockOneShotTimer::SetTaskRunner(
scoped_refptr<SequencedTaskRunner> task_runner) {
NOTREACHED() << "MockOneShotTimer doesn't support SetTaskRunner().";
}
void MockOneShotTimer::Fire() {
DCHECK(IsRunning());
clock_.Advance(std::max(TimeDelta(), desired_run_time() - clock_.NowTicks()));
FlushPendingTasks(test_task_runner_.get());
}
MockRepeatingTimer::MockRepeatingTimer()
: RepeatingTimer(&clock_),
test_task_runner_(MakeRefCounted<TestSimpleTaskRunner>()) {
RepeatingTimer::SetTaskRunner(test_task_runner_);
}
MockRepeatingTimer::~MockRepeatingTimer() = default;
void MockRepeatingTimer::SetTaskRunner(
scoped_refptr<SequencedTaskRunner> task_runner) {
NOTREACHED() << "MockRepeatingTimer doesn't support SetTaskRunner().";
}
void MockRepeatingTimer::Fire() {
DCHECK(IsRunning());
clock_.Advance(std::max(TimeDelta(), desired_run_time() - clock_.NowTicks()));
FlushPendingTasks(test_task_runner_.get());
}
MockRetainingOneShotTimer::MockRetainingOneShotTimer()
: RetainingOneShotTimer(&clock_),
test_task_runner_(MakeRefCounted<TestSimpleTaskRunner>()) {
RetainingOneShotTimer::SetTaskRunner(test_task_runner_);
}
MockRetainingOneShotTimer::~MockRetainingOneShotTimer() = default;
void MockRetainingOneShotTimer::SetTaskRunner(
scoped_refptr<SequencedTaskRunner> task_runner) {
NOTREACHED() << "MockRetainingOneShotTimer doesn't support SetTaskRunner().";
}
void MockRetainingOneShotTimer::Fire() {
DCHECK(IsRunning());
clock_.Advance(std::max(TimeDelta(), desired_run_time() - clock_.NowTicks()));
FlushPendingTasks(test_task_runner_.get());
}
} // namespace base

View file

@ -0,0 +1,76 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TIMER_MOCK_TIMER_H_
#define BASE_TIMER_MOCK_TIMER_H_
#include "base/test/simple_test_tick_clock.h"
#include "base/timer/timer.h"
namespace base {
class TestSimpleTaskRunner;
// A mock implementation of base::OneShotTimer which requires being explicitly
// Fire()'d.
// Prefer using TaskEnvironment::MOCK_TIME + FastForward*() to this when
// possible.
class MockOneShotTimer : public OneShotTimer {
public:
MockOneShotTimer();
~MockOneShotTimer() override;
// Testing method.
void Fire();
private:
// Timer implementation.
// MockOneShotTimer doesn't support SetTaskRunner. Do not use this.
void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) override;
SimpleTestTickClock clock_;
scoped_refptr<TestSimpleTaskRunner> test_task_runner_;
};
// See MockOneShotTimer's comment. Prefer using
// TaskEnvironment::MOCK_TIME.
class MockRepeatingTimer : public RepeatingTimer {
public:
MockRepeatingTimer();
~MockRepeatingTimer() override;
// Testing method.
void Fire();
private:
// Timer implementation.
// MockRepeatingTimer doesn't support SetTaskRunner. Do not use this.
void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) override;
SimpleTestTickClock clock_;
scoped_refptr<TestSimpleTaskRunner> test_task_runner_;
};
// See MockOneShotTimer's comment. Prefer using
// TaskEnvironment::MOCK_TIME.
class MockRetainingOneShotTimer : public RetainingOneShotTimer {
public:
MockRetainingOneShotTimer();
~MockRetainingOneShotTimer() override;
// Testing method.
void Fire();
private:
// Timer implementation.
// MockRetainingOneShotTimer doesn't support SetTaskRunner. Do not use this.
void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) override;
SimpleTestTickClock clock_;
scoped_refptr<TestSimpleTaskRunner> test_task_runner_;
};
} // namespace base
#endif // BASE_TIMER_MOCK_TIMER_H_

View file

@ -0,0 +1,335 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/timer/timer.h"
#include <stddef.h>
#include <utility>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/threading/platform_thread.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/tick_clock.h"
namespace base {
namespace internal {
// BaseTimerTaskInternal is a simple delegate for scheduling a callback to Timer
// on the current sequence. It also handles the following edge cases:
// - deleted by the task runner.
// - abandoned (orphaned) by Timer.
class BaseTimerTaskInternal {
public:
explicit BaseTimerTaskInternal(TimerBase* timer) : timer_(timer) {}
~BaseTimerTaskInternal() {
// This task may be getting cleared because the task runner has been
// destructed. If so, don't leave Timer with a dangling pointer
// to this.
if (timer_)
timer_->AbandonAndStop();
}
void Run() {
// |timer_| is nullptr if we were abandoned.
if (!timer_)
return;
// |this| will be deleted by the task runner, so Timer needs to forget us:
timer_->scheduled_task_ = nullptr;
// Although Timer should not call back into |this|, let's clear |timer_|
// first to be pedantic.
TimerBase* timer = timer_;
timer_ = nullptr;
timer->RunScheduledTask();
}
// The task remains in the queue, but nothing will happen when it runs.
void Abandon() { timer_ = nullptr; }
private:
TimerBase* timer_;
DISALLOW_COPY_AND_ASSIGN(BaseTimerTaskInternal);
};
TimerBase::TimerBase() : TimerBase(nullptr) {}
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
// later calls will verify that the same task runner is used.
origin_sequence_checker_.DetachFromSequence();
}
TimerBase::TimerBase(const Location& posted_from, TimeDelta delay)
: TimerBase(posted_from, delay, nullptr) {}
TimerBase::TimerBase(const Location& posted_from,
TimeDelta delay,
const TickClock* tick_clock)
: scheduled_task_(nullptr),
posted_from_(posted_from),
delay_(delay),
tick_clock_(tick_clock),
is_running_(false) {
// See comment in other constructor.
origin_sequence_checker_.DetachFromSequence();
}
TimerBase::~TimerBase() {
DCHECK(origin_sequence_checker_.CalledOnValidSequence());
AbandonScheduledTask();
}
bool TimerBase::IsRunning() const {
DCHECK(origin_sequence_checker_.CalledOnValidSequence());
return is_running_;
}
TimeDelta TimerBase::GetCurrentDelay() const {
DCHECK(origin_sequence_checker_.CalledOnValidSequence());
return delay_;
}
void TimerBase::SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) {
DCHECK(origin_sequence_checker_.CalledOnValidSequence());
DCHECK(task_runner->RunsTasksInCurrentSequence());
DCHECK(!IsRunning());
task_runner_.swap(task_runner);
}
void TimerBase::StartInternal(const Location& posted_from, TimeDelta delay) {
DCHECK(origin_sequence_checker_.CalledOnValidSequence());
posted_from_ = posted_from;
delay_ = delay;
Reset();
}
void TimerBase::Stop() {
// TODO(gab): Enable this when it's no longer called racily from
// RunScheduledTask(): https://crbug.com/587199.
// DCHECK(origin_sequence_checker_.CalledOnValidSequence());
is_running_ = false;
// It's safe to destroy or restart Timer on another sequence after Stop().
origin_sequence_checker_.DetachFromSequence();
OnStop();
// No more member accesses here: |this| could be deleted after Stop() call.
}
void TimerBase::Reset() {
DCHECK(origin_sequence_checker_.CalledOnValidSequence());
// If there's no pending task, start one up and return.
if (!scheduled_task_) {
PostNewScheduledTask(delay_);
return;
}
// Set the new |desired_run_time_|.
if (delay_ > TimeDelta::FromMicroseconds(0))
desired_run_time_ = Now() + delay_;
else
desired_run_time_ = TimeTicks();
// We can use the existing scheduled task if it arrives before the new
// |desired_run_time_|.
if (desired_run_time_ >= scheduled_run_time_) {
is_running_ = true;
return;
}
// We can't reuse the |scheduled_task_|, so abandon it and post a new one.
AbandonScheduledTask();
PostNewScheduledTask(delay_);
}
TimeTicks TimerBase::Now() const {
// TODO(gab): Enable this when it's no longer called racily from
// RunScheduledTask(): https://crbug.com/587199.
// DCHECK(origin_sequence_checker_.CalledOnValidSequence());
return tick_clock_ ? tick_clock_->NowTicks() : TimeTicks::Now();
}
void TimerBase::PostNewScheduledTask(TimeDelta delay) {
// TODO(gab): Enable this when it's no longer called racily from
// RunScheduledTask(): https://crbug.com/587199.
// DCHECK(origin_sequence_checker_.CalledOnValidSequence());
DCHECK(!scheduled_task_);
is_running_ = true;
scheduled_task_ = new BaseTimerTaskInternal(this);
if (delay > TimeDelta::FromMicroseconds(0)) {
// TODO(gab): Posting BaseTimerTaskInternal::Run to another sequence makes
// this code racy. https://crbug.com/587199
GetTaskRunner()->PostDelayedTask(
posted_from_,
BindOnce(&BaseTimerTaskInternal::Run, Owned(scheduled_task_)), delay);
scheduled_run_time_ = desired_run_time_ = Now() + delay;
} else {
GetTaskRunner()->PostTask(
posted_from_,
BindOnce(&BaseTimerTaskInternal::Run, Owned(scheduled_task_)));
scheduled_run_time_ = desired_run_time_ = TimeTicks();
}
}
scoped_refptr<SequencedTaskRunner> TimerBase::GetTaskRunner() {
return task_runner_.get() ? task_runner_ : SequencedTaskRunnerHandle::Get();
}
void TimerBase::AbandonScheduledTask() {
// TODO(gab): Enable this when it's no longer called racily from
// RunScheduledTask() -> Stop(): https://crbug.com/587199.
// DCHECK(origin_sequence_checker_.CalledOnValidSequence());
if (scheduled_task_) {
scheduled_task_->Abandon();
scheduled_task_ = nullptr;
}
}
void TimerBase::RunScheduledTask() {
// TODO(gab): Enable this when it's no longer called racily:
// https://crbug.com/587199.
// DCHECK(origin_sequence_checker_.CalledOnValidSequence());
// Task may have been disabled.
if (!is_running_)
return;
// First check if we need to delay the task because of a new target time.
if (desired_run_time_ > scheduled_run_time_) {
// Now() can be expensive, so only call it if we know the user has changed
// the |desired_run_time_|.
TimeTicks now = Now();
// Task runner may have called us late anyway, so only post a continuation
// task if the |desired_run_time_| is in the future.
if (desired_run_time_ > now) {
// Post a new task to span the remaining time.
PostNewScheduledTask(desired_run_time_ - now);
return;
}
}
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());
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(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