| 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 12 matching lines...) Expand all Loading... |
| 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/ThreadTimers.h" | 28 #include "platform/ThreadTimers.h" |
| 29 | 29 |
| 30 #include "platform/PlatformThreadData.h" | 30 #include "platform/PlatformThreadData.h" |
| 31 #include "platform/SharedTimer.h" | 31 #include "platform/SharedTimer.h" |
| 32 #include "platform/Timer.h" | 32 #include "platform/Timer.h" |
| 33 #include "platform/TimerHeap.h" |
| 33 #include "platform/TraceEvent.h" | 34 #include "platform/TraceEvent.h" |
| 34 #include "platform/scheduler/Scheduler.h" | 35 #include "platform/scheduler/Scheduler.h" |
| 35 #include "wtf/CurrentTime.h" | 36 #include "wtf/CurrentTime.h" |
| 36 #include "wtf/MainThread.h" | 37 #include "wtf/MainThread.h" |
| 37 | 38 |
| 38 namespace blink { | 39 namespace blink { |
| 39 | 40 |
| 40 // Fire timers for this length of time, and then quit to let the run loop proces
s user input events. | 41 // Fire timers for this length of time, and then quit to let the run loop proces
s user input events. |
| 41 // 100ms is about a perceptable delay in UI, so use a half of that as a threshol
d. | 42 // 100ms is about a perceptable delay in UI, so use a half of that as a threshol
d. |
| 42 // This is to prevent UI freeze when there are too many timers or machine perfor
mance is low. | 43 // This is to prevent UI freeze when there are too many timers or machine perfor
mance is low. |
| 43 static const double maxDurationOfFiringTimers = 0.050; | 44 static const double maxDurationOfFiringTimers = 0.050; |
| 44 | 45 |
| 45 // Timers are created, started and fired on the same thread, and each thread has
its own ThreadTimers | 46 // Timers are created, started and fired on the same thread, and each thread has
its own ThreadTimers |
| 46 // copy to keep the heap and a set of currently firing timers. | 47 // copy to keep the heap and a set of currently firing timers. |
| 47 | 48 |
| 48 static MainThreadSharedTimer* mainThreadSharedTimer() | 49 static MainThreadSharedTimer* mainThreadSharedTimer() |
| 49 { | 50 { |
| 50 static MainThreadSharedTimer* timer = new MainThreadSharedTimer; | 51 static MainThreadSharedTimer* timer = new MainThreadSharedTimer; |
| 51 return timer; | 52 return timer; |
| 52 } | 53 } |
| 53 | 54 |
| 54 ThreadTimers::ThreadTimers() | 55 ThreadTimers::ThreadTimers() |
| 55 : m_sharedTimer(0) | 56 : m_timerHeap(this) |
| 57 , m_sharedTimer(0) |
| 56 , m_firingTimers(false) | 58 , m_firingTimers(false) |
| 57 , m_pendingSharedTimerFireTime(0) | 59 , m_pendingSharedTimerFireTime(0) |
| 58 { | 60 { |
| 59 if (isMainThread()) | 61 if (isMainThread()) |
| 60 setSharedTimer(mainThreadSharedTimer()); | 62 setSharedTimer(mainThreadSharedTimer()); |
| 61 } | 63 } |
| 62 | 64 |
| 63 // A worker thread may initialize SharedTimer after some timers are created. | 65 // A worker thread may initialize SharedTimer after some timers are created. |
| 64 // Also, SharedTimer can be replaced with 0 before all timers are destroyed. | 66 // Also, SharedTimer can be replaced with 0 before all timers are destroyed. |
| 65 void ThreadTimers::setSharedTimer(SharedTimer* sharedTimer) | 67 void ThreadTimers::setSharedTimer(SharedTimer* sharedTimer) |
| 66 { | 68 { |
| 67 if (m_sharedTimer) { | 69 if (m_sharedTimer) { |
| 68 m_sharedTimer->setFiredFunction(0); | 70 m_sharedTimer->setFiredFunction(0); |
| 69 m_sharedTimer->stop(); | 71 m_sharedTimer->stop(); |
| 70 m_pendingSharedTimerFireTime = 0; | 72 m_pendingSharedTimerFireTime = 0; |
| 71 } | 73 } |
| 72 | 74 |
| 73 m_sharedTimer = sharedTimer; | 75 m_sharedTimer = sharedTimer; |
| 74 | 76 |
| 75 if (sharedTimer) { | 77 if (sharedTimer) { |
| 76 m_sharedTimer->setFiredFunction(ThreadTimers::sharedTimerFired); | 78 m_sharedTimer->setFiredFunction(ThreadTimers::sharedTimerFired); |
| 77 updateSharedTimer(); | 79 updateSharedTimer(); |
| 78 } | 80 } |
| 79 } | 81 } |
| 80 | 82 |
| 83 void ThreadTimers::nextFiringTimerChanged() |
| 84 { |
| 85 updateSharedTimer(); |
| 86 } |
| 87 |
| 81 void ThreadTimers::updateSharedTimer() | 88 void ThreadTimers::updateSharedTimer() |
| 82 { | 89 { |
| 83 if (!m_sharedTimer) | 90 if (!m_sharedTimer) |
| 84 return; | 91 return; |
| 85 | 92 |
| 86 if (m_firingTimers || m_timerHeap.isEmpty()) { | 93 if (m_firingTimers || m_timerHeap.isEmpty()) { |
| 87 m_pendingSharedTimerFireTime = 0; | 94 m_pendingSharedTimerFireTime = 0; |
| 88 m_sharedTimer->stop(); | 95 m_sharedTimer->stop(); |
| 89 } else { | 96 } else { |
| 90 double nextFireTime = m_timerHeap.first()->m_nextFireTime; | 97 double nextFireTime = m_timerHeap.first()->nextFireTime(); |
| 91 double currentMonotonicTime = monotonicallyIncreasingTime(); | 98 double currentMonotonicTime = monotonicallyIncreasingTime(); |
| 92 if (m_pendingSharedTimerFireTime) { | 99 if (m_pendingSharedTimerFireTime) { |
| 93 // No need to restart the timer if both the pending fire time and th
e new fire time are in the past. | 100 // No need to restart the timer if both the pending fire time and th
e new fire time are in the past. |
| 94 if (m_pendingSharedTimerFireTime <= currentMonotonicTime && nextFire
Time <= currentMonotonicTime) | 101 if (m_pendingSharedTimerFireTime <= currentMonotonicTime && nextFire
Time <= currentMonotonicTime) |
| 95 return; | 102 return; |
| 96 } | 103 } |
| 97 m_pendingSharedTimerFireTime = nextFireTime; | 104 m_pendingSharedTimerFireTime = nextFireTime; |
| 98 m_sharedTimer->setFireInterval(std::max(nextFireTime - currentMonotonicT
ime, 0.0)); | 105 m_sharedTimer->setFireInterval(std::max(nextFireTime - currentMonotonicT
ime, 0.0)); |
| 99 } | 106 } |
| 100 } | 107 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 113 { | 120 { |
| 114 // Do a re-entrancy check. | 121 // Do a re-entrancy check. |
| 115 if (m_firingTimers) | 122 if (m_firingTimers) |
| 116 return; | 123 return; |
| 117 m_firingTimers = true; | 124 m_firingTimers = true; |
| 118 m_pendingSharedTimerFireTime = 0; | 125 m_pendingSharedTimerFireTime = 0; |
| 119 | 126 |
| 120 double fireTime = monotonicallyIncreasingTime(); | 127 double fireTime = monotonicallyIncreasingTime(); |
| 121 double timeToQuit = fireTime + maxDurationOfFiringTimers; | 128 double timeToQuit = fireTime + maxDurationOfFiringTimers; |
| 122 | 129 |
| 123 while (!m_timerHeap.isEmpty() && m_timerHeap.first()->m_nextFireTime <= fire
Time) { | 130 while (!m_timerHeap.isEmpty() && m_timerHeap.first()->nextFireTime() <= fire
Time) { |
| 124 TimerBase& timer = *m_timerHeap.first(); | 131 TimerBase& timer = *m_timerHeap.first(); |
| 125 timer.m_nextFireTime = 0; | |
| 126 timer.m_unalignedNextFireTime = 0; | |
| 127 timer.heapDeleteMin(); | |
| 128 | |
| 129 double interval = timer.repeatInterval(); | 132 double interval = timer.repeatInterval(); |
| 130 timer.setNextFireTime(interval ? fireTime + interval : 0); | 133 timer.setNextFireTime(interval ? fireTime + interval : 0); |
| 131 | 134 |
| 132 TRACE_EVENT2("blink", "ThreadTimers::sharedTimerFiredInternal", | 135 TRACE_EVENT2("blink", "ThreadTimers::sharedTimerFiredInternal", |
| 133 "src_file", timer.location().fileName(), | 136 "src_file", timer.location().fileName(), |
| 134 "src_func", timer.location().functionName()); | 137 "src_func", timer.location().functionName()); |
| 135 | 138 |
| 136 // Once the timer has been fired, it may be deleted, so do nothing else
with it after this point. | 139 // Once the timer has been fired, it may be deleted, so do nothing else
with it after this point. |
| 137 timer.fired(); | 140 timer.fired(); |
| 138 | 141 |
| 139 // Catch the case where the timer asked timers to fire in a nested event
loop, or we are over time limit. | 142 // Catch the case where the timer asked timers to fire in a nested event
loop, or we are over time limit. |
| 140 if (!m_firingTimers || timeToQuit < monotonicallyIncreasingTime() || (is
MainThread() && Scheduler::shared()->shouldYieldForHighPriorityWork())) | 143 if (!m_firingTimers || timeToQuit < monotonicallyIncreasingTime() || (is
MainThread() && Scheduler::shared()->shouldYieldForHighPriorityWork())) |
| 141 break; | 144 break; |
| 142 } | 145 } |
| 143 | 146 |
| 144 m_firingTimers = false; | 147 m_firingTimers = false; |
| 145 | 148 |
| 146 updateSharedTimer(); | 149 updateSharedTimer(); |
| 147 } | 150 } |
| 148 | 151 |
| 149 void ThreadTimers::fireTimersInNestedEventLoop() | 152 void ThreadTimers::fireTimersInNestedEventLoop() |
| 150 { | 153 { |
| 151 // Reset the reentrancy guard so the timers can fire again. | 154 // Reset the reentrancy guard so the timers can fire again. |
| 152 m_firingTimers = false; | 155 m_firingTimers = false; |
| 153 updateSharedTimer(); | 156 updateSharedTimer(); |
| 154 } | 157 } |
| 155 | 158 |
| 156 } // namespace blink | 159 } // namespace blink |
| 157 | |
| OLD | NEW |