void ThreadTimers::sharedTimerFiredInternal() { // Do a re-entrancy check. if (m_firingTimers) return; m_firingTimers = true; m_pendingSharedTimerFireTime = 0; double fireTime = monotonicallyIncreasingTime(); double timeToQuit = fireTime + maxDurationOfFiringTimers; while (!m_timerHeap.isEmpty() && m_timerHeap.first()->m_nextFireTime <= fireTime) { TimerBase* timer = m_timerHeap.first(); timer->m_nextFireTime = 0; timer->m_unalignedNextFireTime = 0; timer->heapDeleteMin(); double interval = timer->repeatInterval(); timer->setNextFireTime(interval ? fireTime + interval : 0); // Once the timer has been fired, it may be deleted, so do nothing else with it after this point. timer->fired(); // Catch the case where the timer asked timers to fire in a nested event loop, or we are over time limit. if (!m_firingTimers || timeToQuit < monotonicallyIncreasingTime()) break; } m_firingTimers = false; updateSharedTimer(); }
void setDeferringTimers(bool shouldDefer) { if (shouldDefer == deferringTimers) return; deferringTimers = shouldDefer; updateSharedTimer(); }
void TimerBase::setNextFireTime(double newTime) { // Keep heap valid while changing the next-fire time. if (timersReadyToFire) timersReadyToFire->remove(this); double oldTime = m_nextFireTime; if (oldTime != newTime) { m_nextFireTime = newTime; bool wasFirstTimerInHeap = m_heapIndex == 0; if (oldTime == 0) heapInsert(); else if (newTime == 0) heapDelete(); else if (newTime < oldTime) heapDecreaseKey(); else heapIncreaseKey(); bool isFirstTimerInHeap = m_heapIndex == 0; if (wasFirstTimerInHeap || isFirstTimerInHeap) updateSharedTimer(); } checkConsistency(); }
void ThreadTimers::fireTimersInNestedEventLoop() { // Reset the reentrancy guard so the timers can fire again. m_firingTimers = false; if (m_sharedTimer) { m_sharedTimer->invalidate(); m_pendingSharedTimerFireTime = 0; } updateSharedTimer(); }
// A worker thread may initialize SharedTimer after some timers are created. // Also, SharedTimer can be replaced with 0 before all timers are destroyed. void ThreadTimers::setSharedTimer(SharedTimer* sharedTimer) { if (m_sharedTimer) { m_sharedTimer->setFiredFunction(0); m_sharedTimer->stop(); m_pendingSharedTimerFireTime = 0; } m_sharedTimer = sharedTimer; if (sharedTimer) { m_sharedTimer->setFiredFunction(ThreadTimers::sharedTimerFired); updateSharedTimer(); } }
// A worker thread may initialize SharedTimer after some timers are created. // Also, SharedTimer can be replaced with nullptr before all timers are destroyed. void ThreadTimers::setSharedTimer(SharedTimer* sharedTimer) { if (m_sharedTimer) { m_sharedTimer->setFiredFunction(nullptr); m_sharedTimer->stop(); m_pendingSharedTimerFireTime = 0; } m_sharedTimer = sharedTimer; if (sharedTimer) { m_sharedTimer->setFiredFunction([] { threadGlobalData().threadTimers().sharedTimerFiredInternal(); }); updateSharedTimer(); } }
void TimerBase::sharedTimerFired() { // Do a re-entrancy check. if (timersReadyToFire) return; double fireTime = currentTime(); Vector<TimerBase*> firingTimers; HashSet<const TimerBase*> firingTimersSet; timersReadyToFire = &firingTimersSet; collectFiringTimers(fireTime, firingTimers); fireTimers(fireTime, firingTimers); timersReadyToFire = 0; updateSharedTimer(); }
void ThreadTimers::sharedTimerFiredInternal() { // Do a re-entrancy check. if (m_firingTimers) return; m_firingTimers = true; m_pendingSharedTimerFireTime = 0; double fireTime = monotonicallyIncreasingTime(); double timeToQuit = fireTime + maxDurationOfFiringTimers; while (!m_timerHeap.isEmpty() && m_timerHeap.first()->m_nextFireTime <= fireTime) { TimerBase& timer = *m_timerHeap.first(); timer.m_nextFireTime = 0; timer.m_unalignedNextFireTime = 0; timer.heapDeleteMin(); double interval = timer.repeatInterval(); timer.setNextFireTime(interval ? fireTime + interval : 0); TRACE_EVENT2("blink", "ThreadTimers::sharedTimerFiredInternal", "src_file", timer.location().fileName(), "src_func", timer.location().functionName()); // Once the timer has been fired, it may be deleted, so do nothing else with it after this point. timer.fired(); // Catch the case where the timer asked timers to fire in a nested event loop, or we are over time limit. if (!m_firingTimers || timeToQuit < monotonicallyIncreasingTime() || (isMainThread() && Platform::current()->currentThread()->scheduler()->shouldYieldForHighPriorityWork())) break; } m_firingTimers = false; updateSharedTimer(); }
void ThreadTimers::fireTimersInNestedEventLoop() { // Reset the reentrancy guard so the timers can fire again. m_firingTimers = false; updateSharedTimer(); }
void TimerBase::fireTimersInNestedEventLoop() { timersReadyToFire = 0; updateSharedTimer(); }