| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. | 2  * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. | 
| 3  * Copyright (C) 2009 Google Inc. All rights reserved. | 3  * Copyright (C) 2009 Google Inc. All rights reserved. | 
| 4  * | 4  * | 
| 5  * Redistribution and use in source and binary forms, with or without | 5  * Redistribution and use in source and binary forms, with or without | 
| 6  * modification, are permitted provided that the following conditions | 6  * modification, are permitted provided that the following conditions | 
| 7  * are met: | 7  * are met: | 
| 8  * 1. Redistributions of source code must retain the above copyright | 8  * 1. Redistributions of source code must retain the above copyright | 
| 9  *    notice, this list of conditions and the following disclaimer. | 9  *    notice, this list of conditions and the following disclaimer. | 
| 10  * 2. Redistributions in binary form must reproduce the above copyright | 10  * 2. Redistributions in binary form must reproduce the above copyright | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 25  */ | 25  */ | 
| 26 | 26 | 
| 27 #include "config.h" | 27 #include "config.h" | 
| 28 #include "platform/Timer.h" | 28 #include "platform/Timer.h" | 
| 29 | 29 | 
| 30 #include "platform/PlatformThreadData.h" | 30 #include "platform/PlatformThreadData.h" | 
| 31 #include "platform/ThreadTimers.h" | 31 #include "platform/ThreadTimers.h" | 
| 32 #include "wtf/Atomics.h" | 32 #include "platform/TimerHeap.h" | 
| 33 #include "wtf/CurrentTime.h" | 33 #include "wtf/CurrentTime.h" | 
| 34 #include "wtf/HashSet.h" |  | 
| 35 #include <limits.h> |  | 
| 36 #include <math.h> |  | 
| 37 #include <limits> |  | 
| 38 | 34 | 
| 39 namespace blink { | 35 namespace blink { | 
| 40 | 36 | 
| 41 class TimerHeapReference; |  | 
| 42 |  | 
| 43 // Timers are stored in a heap data structure, used to implement a priority queu
     e. |  | 
| 44 // This allows us to efficiently determine which timer needs to fire the soonest
     . |  | 
| 45 // Then we set a single shared system timer to fire at that time. |  | 
| 46 // |  | 
| 47 // When a timer's "next fire time" changes, we need to move it around in the pri
     ority queue. |  | 
| 48 static Vector<TimerBase*>& threadGlobalTimerHeap() |  | 
| 49 { |  | 
| 50     return PlatformThreadData::current().threadTimers().timerHeap(); |  | 
| 51 } |  | 
| 52 // ---------------- |  | 
| 53 |  | 
| 54 class TimerHeapPointer { |  | 
| 55 public: |  | 
| 56     TimerHeapPointer(TimerBase** pointer) : m_pointer(pointer) { } |  | 
| 57     TimerHeapReference operator*() const; |  | 
| 58     TimerBase* operator->() const { return *m_pointer; } |  | 
| 59 private: |  | 
| 60     TimerBase** m_pointer; |  | 
| 61 }; |  | 
| 62 |  | 
| 63 class TimerHeapReference { |  | 
| 64 public: |  | 
| 65     TimerHeapReference(TimerBase*& reference) : m_reference(reference) { } |  | 
| 66     operator TimerBase*() const { return m_reference; } |  | 
| 67     TimerHeapPointer operator&() const { return &m_reference; } |  | 
| 68     TimerHeapReference& operator=(TimerBase*); |  | 
| 69     TimerHeapReference& operator=(TimerHeapReference); |  | 
| 70 private: |  | 
| 71     TimerBase*& m_reference; |  | 
| 72 }; |  | 
| 73 |  | 
| 74 inline TimerHeapReference TimerHeapPointer::operator*() const |  | 
| 75 { |  | 
| 76     return *m_pointer; |  | 
| 77 } |  | 
| 78 |  | 
| 79 inline TimerHeapReference& TimerHeapReference::operator=(TimerBase* timer) |  | 
| 80 { |  | 
| 81     m_reference = timer; |  | 
| 82     Vector<TimerBase*>& heap = timer->timerHeap(); |  | 
| 83     if (&m_reference >= heap.data() && &m_reference < heap.data() + heap.size()) |  | 
| 84         timer->m_heapIndex = &m_reference - heap.data(); |  | 
| 85     return *this; |  | 
| 86 } |  | 
| 87 |  | 
| 88 inline TimerHeapReference& TimerHeapReference::operator=(TimerHeapReference b) |  | 
| 89 { |  | 
| 90     TimerBase* timer = b; |  | 
| 91     return *this = timer; |  | 
| 92 } |  | 
| 93 |  | 
| 94 inline void swap(TimerHeapReference a, TimerHeapReference b) |  | 
| 95 { |  | 
| 96     TimerBase* timerA = a; |  | 
| 97     TimerBase* timerB = b; |  | 
| 98 |  | 
| 99     // Invoke the assignment operator, since that takes care of updating m_heapI
     ndex. |  | 
| 100     a = timerB; |  | 
| 101     b = timerA; |  | 
| 102 } |  | 
| 103 |  | 
| 104 // ---------------- |  | 
| 105 |  | 
| 106 // Class to represent iterators in the heap when calling the standard library he
     ap algorithms. |  | 
| 107 // Uses a custom pointer and reference type that update indices for pointers in 
     the heap. |  | 
| 108 class TimerHeapIterator : public std::iterator<std::random_access_iterator_tag, 
     TimerBase*, ptrdiff_t, TimerHeapPointer, TimerHeapReference> { |  | 
| 109 public: |  | 
| 110     explicit TimerHeapIterator(TimerBase** pointer) : m_pointer(pointer) { check
     Consistency(); } |  | 
| 111 |  | 
| 112     TimerHeapIterator& operator++() { checkConsistency(); ++m_pointer; checkCons
     istency(); return *this; } |  | 
| 113     TimerHeapIterator operator++(int) { checkConsistency(1); return TimerHeapIte
     rator(m_pointer++); } |  | 
| 114 |  | 
| 115     TimerHeapIterator& operator--() { checkConsistency(); --m_pointer; checkCons
     istency(); return *this; } |  | 
| 116     TimerHeapIterator operator--(int) { checkConsistency(-1); return TimerHeapIt
     erator(m_pointer--); } |  | 
| 117 |  | 
| 118     TimerHeapIterator& operator+=(ptrdiff_t i) { checkConsistency(); m_pointer +
     = i; checkConsistency(); return *this; } |  | 
| 119     TimerHeapIterator& operator-=(ptrdiff_t i) { checkConsistency(); m_pointer -
     = i; checkConsistency(); return *this; } |  | 
| 120 |  | 
| 121     TimerHeapReference operator*() const { return TimerHeapReference(*m_pointer)
     ; } |  | 
| 122     TimerHeapReference operator[](ptrdiff_t i) const { return TimerHeapReference
     (m_pointer[i]); } |  | 
| 123     TimerBase* operator->() const { return *m_pointer; } |  | 
| 124 |  | 
| 125 private: |  | 
| 126     void checkConsistency(ptrdiff_t offset = 0) const |  | 
| 127     { |  | 
| 128         ASSERT(m_pointer >= threadGlobalTimerHeap().data()); |  | 
| 129         ASSERT(m_pointer <= threadGlobalTimerHeap().data() + threadGlobalTimerHe
     ap().size()); |  | 
| 130         ASSERT_UNUSED(offset, m_pointer + offset >= threadGlobalTimerHeap().data
     ()); |  | 
| 131         ASSERT_UNUSED(offset, m_pointer + offset <= threadGlobalTimerHeap().data
     () + threadGlobalTimerHeap().size()); |  | 
| 132     } |  | 
| 133 |  | 
| 134     friend bool operator==(TimerHeapIterator, TimerHeapIterator); |  | 
| 135     friend bool operator!=(TimerHeapIterator, TimerHeapIterator); |  | 
| 136     friend bool operator<(TimerHeapIterator, TimerHeapIterator); |  | 
| 137     friend bool operator>(TimerHeapIterator, TimerHeapIterator); |  | 
| 138     friend bool operator<=(TimerHeapIterator, TimerHeapIterator); |  | 
| 139     friend bool operator>=(TimerHeapIterator, TimerHeapIterator); |  | 
| 140 |  | 
| 141     friend TimerHeapIterator operator+(TimerHeapIterator, size_t); |  | 
| 142     friend TimerHeapIterator operator+(size_t, TimerHeapIterator); |  | 
| 143 |  | 
| 144     friend TimerHeapIterator operator-(TimerHeapIterator, size_t); |  | 
| 145     friend ptrdiff_t operator-(TimerHeapIterator, TimerHeapIterator); |  | 
| 146 |  | 
| 147     TimerBase** m_pointer; |  | 
| 148 }; |  | 
| 149 |  | 
| 150 inline bool operator==(TimerHeapIterator a, TimerHeapIterator b) { return a.m_po
     inter == b.m_pointer; } |  | 
| 151 inline bool operator!=(TimerHeapIterator a, TimerHeapIterator b) { return a.m_po
     inter != b.m_pointer; } |  | 
| 152 inline bool operator<(TimerHeapIterator a, TimerHeapIterator b) { return a.m_poi
     nter < b.m_pointer; } |  | 
| 153 inline bool operator>(TimerHeapIterator a, TimerHeapIterator b) { return a.m_poi
     nter > b.m_pointer; } |  | 
| 154 inline bool operator<=(TimerHeapIterator a, TimerHeapIterator b) { return a.m_po
     inter <= b.m_pointer; } |  | 
| 155 inline bool operator>=(TimerHeapIterator a, TimerHeapIterator b) { return a.m_po
     inter >= b.m_pointer; } |  | 
| 156 |  | 
| 157 inline TimerHeapIterator operator+(TimerHeapIterator a, size_t b) { return Timer
     HeapIterator(a.m_pointer + b); } |  | 
| 158 inline TimerHeapIterator operator+(size_t a, TimerHeapIterator b) { return Timer
     HeapIterator(a + b.m_pointer); } |  | 
| 159 |  | 
| 160 inline TimerHeapIterator operator-(TimerHeapIterator a, size_t b) { return Timer
     HeapIterator(a.m_pointer - b); } |  | 
| 161 inline ptrdiff_t operator-(TimerHeapIterator a, TimerHeapIterator b) { return a.
     m_pointer - b.m_pointer; } |  | 
| 162 |  | 
| 163 // ---------------- |  | 
| 164 |  | 
| 165 class TimerHeapLessThanFunction { |  | 
| 166 public: |  | 
| 167     bool operator()(const TimerBase*, const TimerBase*) const; |  | 
| 168 }; |  | 
| 169 |  | 
| 170 inline bool TimerHeapLessThanFunction::operator()(const TimerBase* a, const Time
     rBase* b) const |  | 
| 171 { |  | 
| 172     // The comparisons below are "backwards" because the heap puts the largest |  | 
| 173     // element first and we want the lowest time to be the first one in the heap
     . |  | 
| 174     double aFireTime = a->m_nextFireTime; |  | 
| 175     double bFireTime = b->m_nextFireTime; |  | 
| 176     if (bFireTime != aFireTime) |  | 
| 177         return bFireTime < aFireTime; |  | 
| 178 |  | 
| 179     // We need to look at the difference of the insertion orders instead of comp
     aring the two |  | 
| 180     // outright in case of overflow. |  | 
| 181     unsigned difference = a->m_heapInsertionOrder - b->m_heapInsertionOrder; |  | 
| 182     return difference < std::numeric_limits<unsigned>::max() / 2; |  | 
| 183 } |  | 
| 184 |  | 
| 185 // ---------------- |  | 
| 186 |  | 
| 187 TimerBase::TimerBase() | 37 TimerBase::TimerBase() | 
| 188     : m_nextFireTime(0) | 38     : m_unalignedNextFireTime(0) | 
| 189     , m_unalignedNextFireTime(0) |  | 
| 190     , m_repeatInterval(0) | 39     , m_repeatInterval(0) | 
| 191     , m_heapIndex(-1) | 40     , m_heapEntry(&TimerHeap::get()) | 
| 192     , m_cachedThreadGlobalTimerHeap(0) |  | 
| 193 #if ENABLE(ASSERT) | 41 #if ENABLE(ASSERT) | 
| 194     , m_thread(currentThread()) | 42     , m_thread(currentThread()) | 
| 195 #endif | 43 #endif | 
| 196 { | 44 { | 
| 197 } | 45 } | 
| 198 | 46 | 
| 199 TimerBase::~TimerBase() | 47 TimerBase::~TimerBase() | 
| 200 { | 48 { | 
| 201     stop(); | 49     stop(); | 
| 202     ASSERT(!inHeap()); | 50     ASSERT(!m_heapEntry.inHeap()); | 
| 203 } | 51 } | 
| 204 | 52 | 
| 205 void TimerBase::start(double nextFireInterval, double repeatInterval, const WebT
     raceLocation& caller) | 53 void TimerBase::start(double nextFireInterval, double repeatInterval, const WebT
     raceLocation& caller) | 
| 206 { | 54 { | 
| 207     ASSERT(m_thread == currentThread()); | 55     ASSERT(m_thread == currentThread()); | 
| 208 | 56 | 
| 209     m_location = caller; | 57     m_location = caller; | 
| 210     m_repeatInterval = repeatInterval; | 58     m_repeatInterval = repeatInterval; | 
| 211     setNextFireTime(monotonicallyIncreasingTime() + nextFireInterval); | 59     setNextFireTime(monotonicallyIncreasingTime() + nextFireInterval); | 
| 212 } | 60 } | 
| 213 | 61 | 
| 214 void TimerBase::stop() | 62 void TimerBase::stop() | 
| 215 { | 63 { | 
| 216     ASSERT(m_thread == currentThread()); | 64     ASSERT(m_thread == currentThread()); | 
| 217 | 65 | 
| 218     m_repeatInterval = 0; | 66     m_repeatInterval = 0; | 
| 219     setNextFireTime(0); | 67     setNextFireTime(0); | 
| 220 | 68 | 
| 221     ASSERT(m_nextFireTime == 0); | 69     ASSERT(nextFireTime() == 0); | 
| 222     ASSERT(m_repeatInterval == 0); | 70     ASSERT(m_repeatInterval == 0); | 
| 223     ASSERT(!inHeap()); | 71     ASSERT(!m_heapEntry.inHeap()); | 
| 224 } | 72 } | 
| 225 | 73 | 
| 226 double TimerBase::nextFireInterval() const | 74 double TimerBase::nextFireInterval() const | 
| 227 { | 75 { | 
| 228     ASSERT(isActive()); | 76     ASSERT(isActive()); | 
| 229     double current = monotonicallyIncreasingTime(); | 77     double current = monotonicallyIncreasingTime(); | 
| 230     if (m_nextFireTime < current) | 78     if (nextFireTime() < current) | 
| 231         return 0; | 79         return 0; | 
| 232     return m_nextFireTime - current; | 80     return nextFireTime() - current; | 
| 233 } |  | 
| 234 |  | 
| 235 inline void TimerBase::checkHeapIndex() const |  | 
| 236 { |  | 
| 237     ASSERT(timerHeap() == threadGlobalTimerHeap()); |  | 
| 238     ASSERT(!timerHeap().isEmpty()); |  | 
| 239     ASSERT(m_heapIndex >= 0); |  | 
| 240     ASSERT(m_heapIndex < static_cast<int>(timerHeap().size())); |  | 
| 241     ASSERT(timerHeap()[m_heapIndex] == this); |  | 
| 242 } |  | 
| 243 |  | 
| 244 inline void TimerBase::checkConsistency() const |  | 
| 245 { |  | 
| 246     // Timers should be in the heap if and only if they have a non-zero next fir
     e time. |  | 
| 247     ASSERT(inHeap() == (m_nextFireTime != 0)); |  | 
| 248     if (inHeap()) |  | 
| 249         checkHeapIndex(); |  | 
| 250 } |  | 
| 251 |  | 
| 252 void TimerBase::heapDecreaseKey() |  | 
| 253 { |  | 
| 254     ASSERT(m_nextFireTime != 0); |  | 
| 255     checkHeapIndex(); |  | 
| 256     TimerBase** heapData = timerHeap().data(); |  | 
| 257     push_heap(TimerHeapIterator(heapData), TimerHeapIterator(heapData + m_heapIn
     dex + 1), TimerHeapLessThanFunction()); |  | 
| 258     checkHeapIndex(); |  | 
| 259 } |  | 
| 260 |  | 
| 261 inline void TimerBase::heapDelete() |  | 
| 262 { |  | 
| 263     ASSERT(m_nextFireTime == 0); |  | 
| 264     heapPop(); |  | 
| 265     timerHeap().removeLast(); |  | 
| 266     m_heapIndex = -1; |  | 
| 267 } |  | 
| 268 |  | 
| 269 void TimerBase::heapDeleteMin() |  | 
| 270 { |  | 
| 271     ASSERT(m_nextFireTime == 0); |  | 
| 272     heapPopMin(); |  | 
| 273     timerHeap().removeLast(); |  | 
| 274     m_heapIndex = -1; |  | 
| 275 } |  | 
| 276 |  | 
| 277 inline void TimerBase::heapIncreaseKey() |  | 
| 278 { |  | 
| 279     ASSERT(m_nextFireTime != 0); |  | 
| 280     heapPop(); |  | 
| 281     heapDecreaseKey(); |  | 
| 282 } |  | 
| 283 |  | 
| 284 inline void TimerBase::heapInsert() |  | 
| 285 { |  | 
| 286     ASSERT(!inHeap()); |  | 
| 287     timerHeap().append(this); |  | 
| 288     m_heapIndex = timerHeap().size() - 1; |  | 
| 289     heapDecreaseKey(); |  | 
| 290 } |  | 
| 291 |  | 
| 292 inline void TimerBase::heapPop() |  | 
| 293 { |  | 
| 294     // Temporarily force this timer to have the minimum key so we can pop it. |  | 
| 295     double fireTime = m_nextFireTime; |  | 
| 296     m_nextFireTime = -std::numeric_limits<double>::infinity(); |  | 
| 297     heapDecreaseKey(); |  | 
| 298     heapPopMin(); |  | 
| 299     m_nextFireTime = fireTime; |  | 
| 300 } |  | 
| 301 |  | 
| 302 void TimerBase::heapPopMin() |  | 
| 303 { |  | 
| 304     ASSERT(this == timerHeap().first()); |  | 
| 305     checkHeapIndex(); |  | 
| 306     Vector<TimerBase*>& heap = timerHeap(); |  | 
| 307     TimerBase** heapData = heap.data(); |  | 
| 308     pop_heap(TimerHeapIterator(heapData), TimerHeapIterator(heapData + heap.size
     ()), TimerHeapLessThanFunction()); |  | 
| 309     checkHeapIndex(); |  | 
| 310     ASSERT(this == timerHeap().last()); |  | 
| 311 } |  | 
| 312 |  | 
| 313 static inline bool parentHeapPropertyHolds(const TimerBase* current, const Vecto
     r<TimerBase*>& heap, unsigned currentIndex) |  | 
| 314 { |  | 
| 315     if (!currentIndex) |  | 
| 316         return true; |  | 
| 317     unsigned parentIndex = (currentIndex - 1) / 2; |  | 
| 318     TimerHeapLessThanFunction compareHeapPosition; |  | 
| 319     return compareHeapPosition(current, heap[parentIndex]); |  | 
| 320 } |  | 
| 321 |  | 
| 322 static inline bool childHeapPropertyHolds(const TimerBase* current, const Vector
     <TimerBase*>& heap, unsigned childIndex) |  | 
| 323 { |  | 
| 324     if (childIndex >= heap.size()) |  | 
| 325         return true; |  | 
| 326     TimerHeapLessThanFunction compareHeapPosition; |  | 
| 327     return compareHeapPosition(heap[childIndex], current); |  | 
| 328 } |  | 
| 329 |  | 
| 330 bool TimerBase::hasValidHeapPosition() const |  | 
| 331 { |  | 
| 332     ASSERT(m_nextFireTime); |  | 
| 333     if (!inHeap()) |  | 
| 334         return false; |  | 
| 335     // Check if the heap property still holds with the new fire time. If it does
      we don't need to do anything. |  | 
| 336     // This assumes that the STL heap is a standard binary heap. In an unlikely 
     event it is not, the assertions |  | 
| 337     // in updateHeapIfNeeded() will get hit. |  | 
| 338     const Vector<TimerBase*>& heap = timerHeap(); |  | 
| 339     if (!parentHeapPropertyHolds(this, heap, m_heapIndex)) |  | 
| 340         return false; |  | 
| 341     unsigned childIndex1 = 2 * m_heapIndex + 1; |  | 
| 342     unsigned childIndex2 = childIndex1 + 1; |  | 
| 343     return childHeapPropertyHolds(this, heap, childIndex1) && childHeapPropertyH
     olds(this, heap, childIndex2); |  | 
| 344 } |  | 
| 345 |  | 
| 346 void TimerBase::updateHeapIfNeeded(double oldTime) |  | 
| 347 { |  | 
| 348     if (m_nextFireTime && hasValidHeapPosition()) |  | 
| 349         return; |  | 
| 350 #if ENABLE(ASSERT) |  | 
| 351     int oldHeapIndex = m_heapIndex; |  | 
| 352 #endif |  | 
| 353     if (!oldTime) |  | 
| 354         heapInsert(); |  | 
| 355     else if (!m_nextFireTime) |  | 
| 356         heapDelete(); |  | 
| 357     else if (m_nextFireTime < oldTime) |  | 
| 358         heapDecreaseKey(); |  | 
| 359     else |  | 
| 360         heapIncreaseKey(); |  | 
| 361     ASSERT(m_heapIndex != oldHeapIndex); |  | 
| 362     ASSERT(!inHeap() || hasValidHeapPosition()); |  | 
| 363 } | 81 } | 
| 364 | 82 | 
| 365 void TimerBase::setNextFireTime(double newUnalignedTime) | 83 void TimerBase::setNextFireTime(double newUnalignedTime) | 
| 366 { | 84 { | 
| 367     ASSERT(m_thread == currentThread()); | 85     ASSERT(m_thread == currentThread()); | 
| 368 | 86 | 
| 369     if (m_unalignedNextFireTime != newUnalignedTime) | 87     if (m_unalignedNextFireTime != newUnalignedTime) | 
| 370         m_unalignedNextFireTime = newUnalignedTime; | 88         m_unalignedNextFireTime = newUnalignedTime; | 
| 371 | 89 | 
| 372     // Accessing thread global data is slow. Cache the heap pointer. | 90     double oldTime = nextFireTime(); | 
| 373     if (!m_cachedThreadGlobalTimerHeap) |  | 
| 374         m_cachedThreadGlobalTimerHeap = &threadGlobalTimerHeap(); |  | 
| 375 |  | 
| 376     // Keep heap valid while changing the next-fire time. |  | 
| 377     double oldTime = m_nextFireTime; |  | 
| 378     double newTime = alignedFireTime(newUnalignedTime); | 91     double newTime = alignedFireTime(newUnalignedTime); | 
| 379     if (oldTime != newTime) { | 92     if (oldTime != newTime) | 
| 380         m_nextFireTime = newTime; | 93         m_heapEntry.setValue(*this, newTime); | 
| 381         static unsigned currentHeapInsertionOrder; |  | 
| 382         m_heapInsertionOrder = atomicAdd(¤tHeapInsertionOrder, 1); |  | 
| 383 |  | 
| 384         bool wasFirstTimerInHeap = m_heapIndex == 0; |  | 
| 385 |  | 
| 386         updateHeapIfNeeded(oldTime); |  | 
| 387 |  | 
| 388         bool isFirstTimerInHeap = m_heapIndex == 0; |  | 
| 389 |  | 
| 390         if (wasFirstTimerInHeap || isFirstTimerInHeap) |  | 
| 391             PlatformThreadData::current().threadTimers().updateSharedTimer(); |  | 
| 392     } |  | 
| 393 |  | 
| 394     checkConsistency(); |  | 
| 395 } | 94 } | 
| 396 | 95 | 
| 397 void TimerBase::fireTimersInNestedEventLoop() | 96 void TimerBase::fireTimersInNestedEventLoop() | 
| 398 { | 97 { | 
| 399     // Redirect to ThreadTimers. | 98     // Redirect to ThreadTimers. | 
| 400     PlatformThreadData::current().threadTimers().fireTimersInNestedEventLoop(); | 99     PlatformThreadData::current().threadTimers().fireTimersInNestedEventLoop(); | 
| 401 } | 100 } | 
| 402 | 101 | 
| 403 void TimerBase::didChangeAlignmentInterval() | 102 void TimerBase::didChangeAlignmentInterval() | 
| 404 { | 103 { | 
| 405     setNextFireTime(m_unalignedNextFireTime); | 104     setNextFireTime(m_unalignedNextFireTime); | 
| 406 } | 105 } | 
| 407 | 106 | 
| 408 double TimerBase::nextUnalignedFireInterval() const | 107 double TimerBase::nextUnalignedFireInterval() const | 
| 409 { | 108 { | 
| 410     ASSERT(isActive()); | 109     ASSERT(isActive()); | 
| 411     return std::max(m_unalignedNextFireTime - monotonicallyIncreasingTime(), 0.0
     ); | 110     return std::max(m_unalignedNextFireTime - monotonicallyIncreasingTime(), 0.0
     ); | 
| 412 } | 111 } | 
| 413 | 112 | 
| 414 } // namespace blink | 113 } // namespace blink | 
| OLD | NEW | 
|---|