Chromium Code Reviews| 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 5d2f20bee6fd41695b9bcf84d85bd2ca50138163..5d278652cb03f7b5c8bc17fba1c77f95b1527dfd 100644 |
| --- a/cc/scheduler/delay_based_time_source.cc |
| +++ b/cc/scheduler/delay_based_time_source.cc |
| @@ -15,10 +15,10 @@ namespace cc { |
| namespace { |
| -// kDoubleTickThreshold prevents ticks from running within the specified |
| +// kDoubleTickDivisor prevents ticks from running within the specified |
| // fraction of an interval. This helps account for jitter in the timebase as |
| // well as quick timer reactivation. |
| -static const double kDoubleTickThreshold = 0.25; |
| +static const int kDoubleTickDivisor = 4; |
| // kIntervalChangeThreshold is the fraction of the interval that will trigger an |
| // immediate interval change. kPhaseChangeThreshold is the fraction of the |
| @@ -40,10 +40,10 @@ scoped_refptr<DelayBasedTimeSource> DelayBasedTimeSource::Create( |
| DelayBasedTimeSource::DelayBasedTimeSource( |
| base::TimeDelta interval, base::SingleThreadTaskRunner* task_runner) |
| : client_(NULL), |
| - has_tick_target_(false), |
| + last_tick_time_(base::TimeTicks() - interval), |
| current_parameters_(interval, base::TimeTicks()), |
| next_parameters_(interval, base::TimeTicks()), |
| - state_(STATE_INACTIVE), |
| + active_(false), |
| task_runner_(task_runner), |
| weak_factory_(this) {} |
| @@ -51,32 +51,19 @@ DelayBasedTimeSource::~DelayBasedTimeSource() {} |
| void DelayBasedTimeSource::SetActive(bool active) { |
| TRACE_EVENT1("cc", "DelayBasedTimeSource::SetActive", "active", active); |
| - if (!active) { |
| - state_ = STATE_INACTIVE; |
| - weak_factory_.InvalidateWeakPtrs(); |
| + if (active == active_) |
| return; |
| - } |
| + active_ = active; |
| - if (state_ == STATE_STARTING || state_ == STATE_ACTIVE) |
| - return; |
| - |
| - if (!has_tick_target_) { |
| - // Becoming active the first time is deferred: we post a 0-delay task. |
| - // When it runs, we use that to establish the timebase, become truly |
| - // active, and fire the first tick. |
| - state_ = STATE_STARTING; |
| - task_runner_->PostTask(FROM_HERE, |
| - base::Bind(&DelayBasedTimeSource::OnTimerFired, |
| - weak_factory_.GetWeakPtr())); |
| + if (!active_) { |
| + weak_factory_.InvalidateWeakPtrs(); |
| return; |
| } |
| - state_ = STATE_ACTIVE; |
| - |
| PostNextTickTask(Now()); |
| } |
| -bool DelayBasedTimeSource::Active() const { return state_ != STATE_INACTIVE; } |
| +bool DelayBasedTimeSource::Active() const { return active_; } |
| base::TimeTicks DelayBasedTimeSource::LastTickTime() { return last_tick_time_; } |
| @@ -85,17 +72,11 @@ base::TimeTicks DelayBasedTimeSource::NextTickTime() { |
| } |
| void DelayBasedTimeSource::OnTimerFired() { |
| - DCHECK(state_ != STATE_INACTIVE); |
| - |
| - base::TimeTicks now = this->Now(); |
| - last_tick_time_ = now; |
| + DCHECK(active_); |
| - if (state_ == STATE_STARTING) { |
| - SetTimebaseAndInterval(now, current_parameters_.interval); |
| - state_ = STATE_ACTIVE; |
| - } |
| + last_tick_time_ = current_parameters_.tick_target; |
| - PostNextTickTask(now); |
| + PostNextTickTask(Now()); |
| // Fire the tick. |
| if (client_) |
| @@ -110,9 +91,8 @@ void DelayBasedTimeSource::SetTimebaseAndInterval(base::TimeTicks timebase, |
| base::TimeDelta interval) { |
| next_parameters_.interval = interval; |
| next_parameters_.tick_target = timebase; |
| - has_tick_target_ = true; |
| - if (state_ != STATE_ACTIVE) { |
| + if (!active_) { |
| // If we aren't active, there's no need to reset the timer. |
| return; |
| } |
| @@ -123,6 +103,7 @@ void DelayBasedTimeSource::SetTimebaseAndInterval(base::TimeTicks timebase, |
| std::abs((interval - current_parameters_.interval).InSecondsF()); |
| double interval_change = interval_delta / interval.InSecondsF(); |
| if (interval_change > kIntervalChangeThreshold) { |
| + TRACE_EVENT0("cc", "DelayBasedTimeSource::IntervalChanged"); |
|
nduca
2013/07/03 05:37:25
I'd suggest using an instant event with thread sco
|
| SetActive(false); |
| SetActive(true); |
| return; |
| @@ -140,6 +121,7 @@ void DelayBasedTimeSource::SetTimebaseAndInterval(base::TimeTicks timebase, |
| fmod(target_delta, interval.InSecondsF()) / interval.InSecondsF(); |
| if (phase_change > kPhaseChangeThreshold && |
| phase_change < (1.0 - kPhaseChangeThreshold)) { |
| + TRACE_EVENT0("cc", "DelayBasedTimeSource::PhaseChanged"); |
| SetActive(false); |
| SetActive(true); |
| return; |
| @@ -205,26 +187,24 @@ base::TimeTicks DelayBasedTimeSource::Now() const { |
| // 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) { |
| + const base::TimeDelta epsilon(base::TimeDelta::FromMicroseconds(1)); |
| base::TimeDelta new_interval = next_parameters_.interval; |
| int intervals_elapsed = |
| - static_cast<int>(floor((now - next_parameters_.tick_target).InSecondsF() / |
| - new_interval.InSecondsF())); |
| - base::TimeTicks last_effective_tick = |
| + (now - next_parameters_.tick_target + new_interval - epsilon) / |
| + new_interval; |
| + base::TimeTicks new_tick_target = |
| next_parameters_.tick_target + new_interval * intervals_elapsed; |
| - base::TimeTicks new_tick_target = last_effective_tick + new_interval; |
| - DCHECK(now < new_tick_target) |
| + DCHECK(now <= new_tick_target) |
| << "now = " << now.ToInternalValue() |
| << "; new_tick_target = " << new_tick_target.ToInternalValue() |
| << "; new_interval = " << new_interval.InMicroseconds() |
| << "; tick_target = " << next_parameters_.tick_target.ToInternalValue() |
| - << "; intervals_elapsed = " << intervals_elapsed |
| - << "; last_effective_tick = " << last_effective_tick.ToInternalValue(); |
| + << "; intervals_elapsed = " << intervals_elapsed; |
| // 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_ <= |
| - new_interval / static_cast<int>(1.0 / kDoubleTickThreshold)) |
| + if (new_tick_target - last_tick_time_ <= new_interval / kDoubleTickDivisor) |
| new_tick_target += new_interval; |
| return new_tick_target; |
| @@ -234,10 +214,9 @@ void DelayBasedTimeSource::PostNextTickTask(base::TimeTicks now) { |
| base::TimeTicks new_tick_target = NextTickTarget(now); |
| // Post another task *before* the tick and update state |
| - base::TimeDelta delay = new_tick_target - now; |
| - DCHECK(delay.InMillisecondsF() <= |
| - next_parameters_.interval.InMillisecondsF() * |
| - (1.0 + kDoubleTickThreshold)); |
| + base::TimeDelta delay; |
| + if (now <= new_tick_target) |
| + delay = new_tick_target - now; |
| task_runner_->PostDelayedTask(FROM_HERE, |
| base::Bind(&DelayBasedTimeSource::OnTimerFired, |
| weak_factory_.GetWeakPtr()), |