Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2564)

Unified Diff: cc/scheduler/delay_based_time_source.cc

Issue 1200113003: cc: Cleanup DelayBasedTimeSource code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@task_runner_refptr
Patch Set: Fix race between missed tick and normal tick Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: cc/scheduler/delay_based_time_source.cc
diff --git a/cc/scheduler/delay_based_time_source.cc b/cc/scheduler/delay_based_time_source.cc
index b1f68bd27c94fda46cd5919eed1a76326feeeedb..1f8e92dfefb7f3897114419ab2dd347660420419 100644
--- a/cc/scheduler/delay_based_time_source.cc
+++ b/cc/scheduler/delay_based_time_source.cc
@@ -42,40 +42,49 @@ DelayBasedTimeSource::DelayBasedTimeSource(
base::SingleThreadTaskRunner* task_runner)
: client_(NULL),
last_tick_time_(base::TimeTicks() - interval),
- current_parameters_(interval, base::TimeTicks()),
- next_parameters_(interval, base::TimeTicks()),
+ next_tick_time_(base::TimeTicks()),
+ timebase_(base::TimeTicks()),
+ interval_(interval),
active_(false),
task_runner_(task_runner),
weak_factory_(this) {
- DCHECK_GT(interval.ToInternalValue(), 0);
+ DCHECK_GT(interval, base::TimeDelta());
}
DelayBasedTimeSource::~DelayBasedTimeSource() {}
-base::TimeTicks DelayBasedTimeSource::SetActive(bool active) {
+void DelayBasedTimeSource::SetActive(bool active) {
TRACE_EVENT1("cc", "DelayBasedTimeSource::SetActive", "active", active);
if (active == active_)
- return base::TimeTicks();
+ return;
active_ = active;
if (!active_) {
+ next_tick_time_ = base::TimeTicks();
weak_factory_.InvalidateWeakPtrs();
mithro-old 2015/06/30 08:11:52 It's really weird that this works by invalidating
- return base::TimeTicks();
+ return;
}
- PostNextTickTask(Now());
+ base::TimeTicks now = Now();
+ base::TimeTicks next_tick_target = NextTickTarget(now);
// Determine if there was a tick that was missed while not active.
base::TimeTicks last_tick_time_if_always_active =
- current_parameters_.tick_target - current_parameters_.interval;
- base::TimeTicks new_tick_time_threshold =
- last_tick_time_ + current_parameters_.interval / kDoubleTickDivisor;
- if (last_tick_time_if_always_active > new_tick_time_threshold) {
- last_tick_time_ = last_tick_time_if_always_active;
- return last_tick_time_;
+ next_tick_target - interval_;
+ base::TimeTicks last_tick_time_threshold =
+ last_tick_time_ + interval_ / kDoubleTickDivisor;
+ if (last_tick_time_if_always_active > last_tick_time_threshold) {
+ missed_tick_time_ = last_tick_time_if_always_active;
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&DelayBasedTimeSource::OnMissedTick,
brianderson 2015/06/26 19:24:35 Can you bind to a Closure (in the constructor and
+ weak_factory_.GetWeakPtr()));
}
- return base::TimeTicks();
+ PostNextTickTask(now);
+}
+
+base::TimeDelta DelayBasedTimeSource::Interval() const {
+ return interval_;
}
bool DelayBasedTimeSource::Active() const { return active_; }
@@ -84,14 +93,27 @@ base::TimeTicks DelayBasedTimeSource::LastTickTime() const {
return last_tick_time_;
}
+base::TimeTicks DelayBasedTimeSource::MissedTickTime() const {
brianderson 2015/06/26 19:24:34 Is this needed? Looks like Client::OnMissedTick ca
+ return missed_tick_time_;
+}
+
base::TimeTicks DelayBasedTimeSource::NextTickTime() const {
- return Active() ? current_parameters_.tick_target : base::TimeTicks();
+ return next_tick_time_;
brianderson 2015/06/26 19:24:34 Probably doesn't matter for the current user of th
}
-void DelayBasedTimeSource::OnTimerFired() {
+void DelayBasedTimeSource::OnMissedTick() {
brianderson 2015/06/26 19:24:34 Should missed_tick_time_ be reset somewhere in thi
DCHECK(active_);
- last_tick_time_ = current_parameters_.tick_target;
+ last_tick_time_ = missed_tick_time_;
+
+ if (client_)
+ client_->OnMissedTick();
+}
+
+void DelayBasedTimeSource::OnTimerTick() {
+ DCHECK(active_);
+
+ last_tick_time_ = next_tick_time_;
PostNextTickTask(Now());
@@ -100,31 +122,31 @@ void DelayBasedTimeSource::OnTimerFired() {
client_->OnTimerTick();
}
-void DelayBasedTimeSource::SetClient(TimeSourceClient* client) {
+void DelayBasedTimeSource::SetClient(DelayBasedTimeSourceClient* client) {
client_ = client;
}
void DelayBasedTimeSource::SetTimebaseAndInterval(base::TimeTicks timebase,
base::TimeDelta interval) {
- DCHECK_GT(interval.ToInternalValue(), 0);
- next_parameters_.interval = interval;
- next_parameters_.tick_target = timebase;
-
- if (!active_) {
- // If we aren't active, there's no need to reset the timer.
- return;
- }
+ DCHECK_GT(interval, base::TimeDelta());
// If the change in interval is larger than the change threshold,
// request an immediate reset.
- double interval_delta =
- std::abs((interval - current_parameters_.interval).InSecondsF());
+ double interval_delta = std::abs((interval - interval_).InSecondsF());
+ double target_delta = std::abs((timebase - timebase_).InSecondsF());
+
+ interval_ = interval;
+ timebase_ = timebase;
+
+ // If we aren't active, there's no need to reset the timer.
+ if (!active_)
+ return;
+
double interval_change = interval_delta / interval.InSecondsF();
if (interval_change > kIntervalChangeThreshold) {
TRACE_EVENT_INSTANT0("cc", "DelayBasedTimeSource::IntervalChanged",
TRACE_EVENT_SCOPE_THREAD);
- SetActive(false);
- SetActive(true);
+ ResetTickTask(Now());
return;
}
@@ -134,16 +156,13 @@ void DelayBasedTimeSource::SetTimebaseAndInterval(base::TimeTicks timebase,
// fmod just happens to return something near zero. Assuming the timebase
// is very recent though, which it should be, we'll still be ok because the
// old clock and new clock just happen to line up.
- double target_delta =
- std::abs((timebase - current_parameters_.tick_target).InSecondsF());
double phase_change =
fmod(target_delta, interval.InSecondsF()) / interval.InSecondsF();
if (phase_change > kPhaseChangeThreshold &&
phase_change < (1.0 - kPhaseChangeThreshold)) {
TRACE_EVENT_INSTANT0("cc", "DelayBasedTimeSource::PhaseChanged",
TRACE_EVENT_SCOPE_THREAD);
- SetActive(false);
- SetActive(true);
+ ResetTickTask(Now());
return;
}
}
@@ -206,39 +225,41 @@ base::TimeTicks DelayBasedTimeSource::Now() const {
// is not reset.
// now=37 tick_target=16.667 new_target=50.000 -->
// tick(), PostDelayedTask(floor(50.000-37)) --> PostDelayedTask(13)
-base::TimeTicks DelayBasedTimeSource::NextTickTarget(base::TimeTicks now) {
- base::TimeTicks new_tick_target = now.SnappedToNextTick(
- next_parameters_.tick_target, next_parameters_.interval);
- DCHECK(now <= new_tick_target)
+base::TimeTicks DelayBasedTimeSource::NextTickTarget(
+ base::TimeTicks now) const {
+ base::TimeTicks next_tick_target =
+ now.SnappedToNextTick(timebase_, interval_);
+ DCHECK(now <= next_tick_target)
<< "now = " << now.ToInternalValue()
- << "; new_tick_target = " << new_tick_target.ToInternalValue()
- << "; new_interval = " << next_parameters_.interval.InMicroseconds()
- << "; tick_target = " << next_parameters_.tick_target.ToInternalValue();
+ << "; new_tick_target = " << next_tick_target.ToInternalValue()
+ << "; new_interval = " << interval_.InMicroseconds()
+ << "; tick_target = " << timebase_.ToInternalValue();
// Avoid double ticks when:
// 1) Turning off the timer and turning it right back on.
// 2) Jittery data is passed to SetTimebaseAndInterval().
- if (new_tick_target - last_tick_time_ <=
- next_parameters_.interval / kDoubleTickDivisor)
- new_tick_target += next_parameters_.interval;
+ if (next_tick_target - last_tick_time_ <= interval_ / kDoubleTickDivisor)
+ next_tick_target += interval_;
- return new_tick_target;
+ return next_tick_target;
}
void DelayBasedTimeSource::PostNextTickTask(base::TimeTicks now) {
- base::TimeTicks new_tick_target = NextTickTarget(now);
-
+ base::TimeTicks next_tick_target = NextTickTarget(now);
+ DCHECK(next_tick_target >= now);
// Post another task *before* the tick and update state
- base::TimeDelta delay;
- if (now <= new_tick_target)
- delay = new_tick_target - now;
+ base::TimeDelta delay = next_tick_target - now;
task_runner_->PostDelayedTask(FROM_HERE,
- base::Bind(&DelayBasedTimeSource::OnTimerFired,
+ base::Bind(&DelayBasedTimeSource::OnTimerTick,
brianderson 2015/06/26 19:24:35 Ditto regarding dynamic bind.
weak_factory_.GetWeakPtr()),
delay);
- next_parameters_.tick_target = new_tick_target;
- current_parameters_ = next_parameters_;
+ next_tick_time_ = next_tick_target;
+}
+
+void DelayBasedTimeSource::ResetTickTask(base::TimeTicks now) {
+ weak_factory_.InvalidateWeakPtrs();
+ PostNextTickTask(now);
}
std::string DelayBasedTimeSource::TypeString() const {
@@ -249,21 +270,10 @@ void DelayBasedTimeSource::AsValueInto(
base::trace_event::TracedValue* state) const {
state->SetString("type", TypeString());
state->SetDouble("last_tick_time_us", LastTickTime().ToInternalValue());
+ state->SetDouble("missed_tick_time_us", MissedTickTime().ToInternalValue());
state->SetDouble("next_tick_time_us", NextTickTime().ToInternalValue());
-
- state->BeginDictionary("current_parameters");
- state->SetDouble("interval_us",
- current_parameters_.interval.InMicroseconds());
- state->SetDouble("tick_target_us",
- current_parameters_.tick_target.ToInternalValue());
- state->EndDictionary();
-
- state->BeginDictionary("next_parameters");
- state->SetDouble("interval_us", next_parameters_.interval.InMicroseconds());
- state->SetDouble("tick_target_us",
- next_parameters_.tick_target.ToInternalValue());
- state->EndDictionary();
-
+ state->SetDouble("interval_us", interval_.InMicroseconds());
+ state->SetDouble("timebase_us", timebase_.ToInternalValue());
state->SetBoolean("active", active_);
}

Powered by Google App Engine
This is Rietveld 408576698