Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 class _Timer implements Timer { | 5 class _Timer implements Timer { |
| 6 | 6 |
| 7 /* | 7 /* |
| 8 * Set jitter to wake up timer events that would happen in _TIMER_JITTER ms. | 8 * Set jitter to wake up timer events that would happen in _TIMER_JITTER ms. |
| 9 */ | 9 */ |
| 10 static final int _TIMER_JITTER = 0; | 10 static final int _TIMER_JITTER = 0; |
| 11 | 11 |
| 12 /* | 12 /* |
| 13 * Disables the timer. | 13 * Disables the timer. |
| 14 */ | 14 */ |
| 15 static final int _NO_TIMER = -1; | 15 static final int _NO_TIMER = -1; |
| 16 | 16 |
| 17 factory _Timer(void callback(Timer timer), | 17 factory _Timer(void callback(Timer timer), |
| 18 int milliSeconds, | 18 int milliSeconds, |
| 19 bool repeating) { | 19 bool repeating) { |
| 20 EventHandler._start(); | 20 EventHandler._start(); |
| 21 if (_timers === null) { | 21 if (_timers === null) { |
| 22 _timers = new DoubleLinkedQueue<_Timer>(); | 22 _timers = new DoubleLinkedQueue<_Timer>(); |
| 23 } | 23 } |
| 24 Timer timer = new _Timer._internal(); | 24 Timer timer = new _Timer._internal(); |
| 25 timer._callback = callback; | 25 timer._callback = callback; |
| 26 timer._milliSeconds = milliSeconds; | 26 timer._milliSeconds = milliSeconds; |
| 27 timer._wakeupTime = (new Date.now()).value + milliSeconds; | 27 timer._wakeupTime = (new Date.now()).value + milliSeconds; |
| 28 timer._repeating = repeating; | 28 timer._repeating = repeating; |
| 29 timer._addTimerToList(); | 29 timer._addTimerToList(); |
| 30 timer._notifyEventHandler(); | 30 timer._notifyEventHandler(); |
|
siva
2011/12/16 01:42:02
We need to call notifyEventHandler only if addTime
| |
| 31 return timer; | 31 return timer; |
| 32 } | 32 } |
| 33 | 33 |
| 34 _Timer._internal() {} | 34 _Timer._internal() {} |
| 35 | 35 |
| 36 void _clear() { | 36 void _clear() { |
| 37 _callback = null; | 37 _callback = null; |
| 38 _milliSeconds = 0; | 38 _milliSeconds = 0; |
| 39 _wakeupTime = 0; | 39 _wakeupTime = 0; |
| 40 _repeating = false; | 40 _repeating = false; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 68 | 68 |
| 69 /* | 69 /* |
| 70 * Adds a timer to the timer list and resets the native timer if it is the | 70 * Adds a timer to the timer list and resets the native timer if it is the |
| 71 * earliest timer in the list. Timers with the same wakeup time are enqueued | 71 * earliest timer in the list. Timers with the same wakeup time are enqueued |
| 72 * in order and notified in FIFO order. | 72 * in order and notified in FIFO order. |
| 73 */ | 73 */ |
| 74 void _addTimerToList() { | 74 void _addTimerToList() { |
| 75 if (_callback !== null) { | 75 if (_callback !== null) { |
| 76 | 76 |
| 77 DoubleLinkedQueueEntry<_Timer> entry = _timers.firstEntry(); | 77 DoubleLinkedQueueEntry<_Timer> entry = _timers.firstEntry(); |
| 78 if (entry === null) { | |
| 79 _createTimerHandler(); | |
| 80 } | |
| 81 | |
| 82 while (entry !== null) { | 78 while (entry !== null) { |
| 83 if (_wakeupTime < entry.element._wakeupTime) { | 79 if (_wakeupTime < entry.element._wakeupTime) { |
| 84 entry.prepend(this); | 80 entry.prepend(this); |
| 85 return; | 81 return; |
| 86 } | 82 } |
| 87 entry = entry.nextEntry(); | 83 entry = entry.nextEntry(); |
| 88 } | 84 } |
| 89 _timers.addLast(this); | 85 _timers.addLast(this); |
| 90 } | 86 } |
| 91 } | 87 } |
| 92 | 88 |
| 93 | 89 |
| 94 void _notifyEventHandler() { | 90 void _notifyEventHandler() { |
| 91 if (_handling_callbacks) { | |
| 92 // While we are already handling callbacks we will not notify the event | |
| 93 // handler. _handleTimeout will call _notifyEventHandler once all pending | |
| 94 // timers are processed. | |
| 95 return; | |
| 96 } | |
| 97 | |
| 95 if (_timers.firstEntry() === null) { | 98 if (_timers.firstEntry() === null) { |
| 99 // No pending timers: Close the receive port and let the event handler | |
| 100 // know. | |
| 96 if (_receivePort !== null) { | 101 if (_receivePort !== null) { |
| 97 EventHandler._sendData(-1, _receivePort, _NO_TIMER); | 102 EventHandler._sendData(-1, _receivePort, _NO_TIMER); |
| 98 _shutdownTimerHandler(); | 103 _shutdownTimerHandler(); |
| 99 } | 104 } |
| 100 } else { | 105 } else { |
| 106 if (_receivePort === null) { | |
| 107 // Create a receive port and register a message handler for the timer | |
| 108 // events. | |
| 109 _createTimerHandler(); | |
| 110 } | |
| 101 EventHandler._sendData(-1, | 111 EventHandler._sendData(-1, |
| 102 _receivePort, | 112 _receivePort, |
| 103 _timers.firstEntry().element._wakeupTime); | 113 _timers.firstEntry().element._wakeupTime); |
| 104 } | 114 } |
| 105 } | 115 } |
| 106 | 116 |
| 107 | 117 |
| 108 /* | 118 /* |
| 109 * Creates a receive port and registers the timer handler on that receive | 119 * Creates a receive port and registers the timer handler on that receive |
| 110 * port. | 120 * port. |
| 111 */ | 121 */ |
| 112 void _createTimerHandler() { | 122 void _createTimerHandler() { |
| 113 | 123 |
| 114 void _handleTimeout() { | 124 void _handleTimeout() { |
| 115 int currentTime = (new Date.now()).value + _TIMER_JITTER; | 125 int currentTime = (new Date.now()).value + _TIMER_JITTER; |
| 116 | 126 |
| 127 // Collect all pending timers. | |
| 117 DoubleLinkedQueueEntry<_Timer> entry = _timers.firstEntry(); | 128 DoubleLinkedQueueEntry<_Timer> entry = _timers.firstEntry(); |
| 129 var pending_timers = new List(); | |
| 118 while (entry !== null) { | 130 while (entry !== null) { |
| 119 _Timer timer = entry.element; | 131 _Timer timer = entry.element; |
| 120 if (timer._wakeupTime <= currentTime) { | 132 if (timer._wakeupTime <= currentTime) { |
| 121 entry.remove(); | 133 entry.remove(); |
| 122 timer._callback(timer); | 134 pending_timers.addLast(timer); |
| 123 // Always process the event with the earliest wakeupTime first. | |
| 124 entry = _timers.firstEntry(); | 135 entry = _timers.firstEntry(); |
| 125 if (timer._repeating) { | |
| 126 timer._advanceWakeupTime(); | |
| 127 timer._addTimerToList(); | |
| 128 _notifyEventHandler(); | |
| 129 } | |
| 130 } else { | 136 } else { |
| 131 break; | 137 break; |
| 132 } | 138 } |
| 133 } | 139 } |
| 140 | |
| 141 // Trigger all of the pending timers. New timers added as part of the | |
| 142 // callbacks will be enqueued now and notified in the next spin at the | |
| 143 // earliest. | |
| 144 _handling_callbacks = true; | |
| 145 try { | |
| 146 for (var timer in pending_timers) { | |
| 147 timer._callback(timer); | |
| 148 if (timer._repeating) { | |
| 149 timer._advanceWakeupTime(); | |
| 150 timer._addTimerToList(); | |
| 151 } | |
| 152 } | |
| 153 } finally { | |
| 154 _handling_callbacks = false; | |
| 155 } | |
| 134 _notifyEventHandler(); | 156 _notifyEventHandler(); |
| 135 } | 157 } |
| 136 | 158 |
| 137 if(_receivePort === null) { | 159 if(_receivePort === null) { |
| 138 _receivePort = new ReceivePort(); | 160 _receivePort = new ReceivePort(); |
| 139 _receivePort.receive((var message, ignored) { | 161 _receivePort.receive((var message, ignored) { |
| 140 _handleTimeout(); | 162 _handleTimeout(); |
| 141 }); | 163 }); |
| 142 } | 164 } |
| 143 } | 165 } |
| 144 | 166 |
| 145 void _shutdownTimerHandler() { | 167 void _shutdownTimerHandler() { |
| 146 _receivePort.close(); | 168 _receivePort.close(); |
| 147 _receivePort = null; | 169 _receivePort = null; |
| 148 } | 170 } |
| 149 | 171 |
| 150 | 172 |
| 151 /* | 173 /* |
| 152 * Timers are ordered by wakeup time. | 174 * Timers are ordered by wakeup time. |
| 153 */ | 175 */ |
| 154 static DoubleLinkedQueue<_Timer> _timers; | 176 static DoubleLinkedQueue<_Timer> _timers; |
| 155 | 177 |
| 156 static ReceivePort _receivePort; | 178 static ReceivePort _receivePort; |
| 179 static bool _handling_callbacks = false; | |
| 157 | 180 |
| 158 var _callback; | 181 var _callback; |
| 159 int _milliSeconds; | 182 int _milliSeconds; |
| 160 int _wakeupTime; | 183 int _wakeupTime; |
| 161 bool _repeating; | 184 bool _repeating; |
| 162 } | 185 } |
| 163 | 186 |
| OLD | NEW |