diff options
author | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-02 05:05:47 +0000 |
---|---|---|
committer | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-02 05:05:47 +0000 |
commit | 8f55d97c490d69b936dd98617be09cdccd64ceeb (patch) | |
tree | f70e302506969dc3e986f6404b45361cc5ebc2ea /cc/scheduler/delay_based_time_source.cc | |
parent | cfe4f98a2fbcfff277baa2425873a6601cd523fe (diff) | |
download | chromium_src-8f55d97c490d69b936dd98617be09cdccd64ceeb.zip chromium_src-8f55d97c490d69b936dd98617be09cdccd64ceeb.tar.gz chromium_src-8f55d97c490d69b936dd98617be09cdccd64ceeb.tar.bz2 |
cc: Make DelayBasedTimeSource robust to large deltas
Trying to calculate elapsed intervals is prone to overflow errors. Just
use modular arithmetic to figure out the closest next tick time to now.
R=danakj@chromium.org
BUG=282672
Review URL: https://chromiumcodereview.appspot.com/23839003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@220794 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/scheduler/delay_based_time_source.cc')
-rw-r--r-- | cc/scheduler/delay_based_time_source.cc | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/cc/scheduler/delay_based_time_source.cc b/cc/scheduler/delay_based_time_source.cc index a5b6f73..d150c71 100644 --- a/cc/scheduler/delay_based_time_source.cc +++ b/cc/scheduler/delay_based_time_source.cc @@ -203,27 +203,28 @@ 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; - // Integer division rounds towards 0, but we always want to round down the - // number of intervals_elapsed, so we need the extra condition here. - int intervals_elapsed; - if (next_parameters_.tick_target < now) { - intervals_elapsed = - (now - next_parameters_.tick_target + new_interval - epsilon) / - new_interval; - } else { - intervals_elapsed = (now - next_parameters_.tick_target) / new_interval; + // |interval_offset| is the offset from |now| to the next multiple of + // |interval| after |tick_target|, possibly negative if in the past. + base::TimeDelta interval_offset = base::TimeDelta::FromInternalValue( + (next_parameters_.tick_target - now).ToInternalValue() % + new_interval.ToInternalValue()); + // If |now| is exactly on the interval (i.e. offset==0), don't adjust. + // Otherwise, if |tick_target| was in the past, adjust forward to the next + // tick after |now|. + if (interval_offset.ToInternalValue() != 0 && + next_parameters_.tick_target < now) { + interval_offset += new_interval; } - base::TimeTicks new_tick_target = - next_parameters_.tick_target + new_interval * intervals_elapsed; + + base::TimeTicks new_tick_target = now + interval_offset; 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; + << "; interval_offset = " << interval_offset.ToInternalValue(); // Avoid double ticks when: // 1) Turning off the timer and turning it right back on. |