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 |