/** * Reschedules this timer. * * @param next The time when this timer should be called again. Use -1 to let * the timer figure out a suitable time based on the interval. */ void Timer::Reschedule(double next) { ASSERT(!OwnsLock()); boost::mutex::scoped_lock lock(l_Mutex); if (next < 0) { /* Don't schedule the next call if this is not a periodic timer. */ if (m_Interval <= 0) return; next = Utility::GetTime() + m_Interval; } m_Next = next; if (m_Started) { /* Remove and re-add the timer to update the index. */ l_Timers.erase(GetSelf()); l_Timers.insert(GetSelf()); /* Notify the worker that we've rescheduled a timer. */ l_CV.notify_all(); } }
/** * Reschedules this timer. * * @param completed Whether the timer has just completed its callback. * @param next The time when this timer should be called again. Use -1 to let * the timer figure out a suitable time based on the interval. */ void Timer::InternalReschedule(bool completed, double next) { ASSERT(!OwnsLock()); boost::mutex::scoped_lock lock(l_TimerMutex); if (completed) m_Running = false; if (next < 0) { /* Don't schedule the next call if this is not a periodic timer. */ if (m_Interval <= 0) return; next = Utility::GetTime() + m_Interval; } m_Next = next; if (m_Started && !m_Running) { /* Remove and re-add the timer to update the index. */ l_Timers.erase(this); l_Timers.insert(this); /* Notify the worker that we've rescheduled a timer. */ l_TimerCV.notify_all(); } }
/** * Unregisters the timer and stops processing events for it. */ void Timer::Stop(void) { ASSERT(!OwnsLock()); boost::mutex::scoped_lock lock(l_Mutex); m_Started = false; l_Timers.erase(GetSelf()); /* Notify the worker thread that we've disabled a timer. */ l_CV.notify_all(); }
/** * Adjusts all timers by adding the specified amount of time to their * next scheduled timestamp. * * @param adjustment The adjustment. */ void Timer::AdjustTimers(double adjustment) { boost::mutex::scoped_lock lock(l_TimerMutex); double now = Utility::GetTime(); typedef boost::multi_index::nth_index<TimerSet, 1>::type TimerView; TimerView& idx = boost::get<1>(l_Timers); std::vector<Timer *> timers; BOOST_FOREACH(Timer *timer, idx) { if (std::fabs(now - (timer->m_Next + adjustment)) < std::fabs(now - timer->m_Next)) { timer->m_Next += adjustment; timers.push_back(timer); } } BOOST_FOREACH(Timer *timer, timers) { l_Timers.erase(timer); l_Timers.insert(timer); }
/** * Adjusts all timers by adding the specified amount of time to their * next scheduled timestamp. * * @param adjustment The adjustment. */ void Timer::AdjustTimers(double adjustment) { boost::mutex::scoped_lock lock(l_Mutex); double now = Utility::GetTime(); typedef boost::multi_index::nth_index<TimerSet, 1>::type TimerView; TimerView& idx = boost::get<1>(l_Timers); TimerView::iterator it; for (it = idx.begin(); it != idx.end(); it++) { Timer::Ptr timer = it->lock(); if (abs(now - (timer->m_Next + adjustment)) < abs(now - timer->m_Next)) { timer->m_Next += adjustment; l_Timers.erase(timer); l_Timers.insert(timer); } } /* Notify the worker that we've rescheduled some timers. */ l_CV.notify_all(); }
/** * Worker thread proc for Timer objects. */ void Timer::TimerThreadProc(void) { Utility::SetThreadName("Timer Thread"); for (;;) { boost::mutex::scoped_lock lock(l_Mutex); typedef boost::multi_index::nth_index<TimerSet, 1>::type NextTimerView; NextTimerView& idx = boost::get<1>(l_Timers); /* Wait until there is at least one timer. */ while (idx.empty() && !l_StopThread) l_CV.wait(lock); if (l_StopThread) break; NextTimerView::iterator it = idx.begin(); Timer::Ptr timer = it->lock(); if (!timer) { /* Remove the timer from the list if it's not alive anymore. */ idx.erase(it); continue; } double wait = timer->m_Next - Utility::GetTime(); if (wait > 0) { /* Make sure the timer we just examined can be destroyed while we're waiting. */ timer.reset(); /* Wait for the next timer. */ l_CV.timed_wait(lock, boost::posix_time::milliseconds(wait * 1000)); continue; } /* Remove the timer from the list so it doesn't get called again * until the current call is completed. */ l_Timers.erase(timer); lock.unlock(); /* Asynchronously call the timer. */ Utility::QueueAsyncCallback(boost::bind(&Timer::Call, timer)); } }
/** * Unregisters the timer and stops processing events for it. */ void Timer::Stop(bool wait) { ASSERT(!OwnsLock()); if (l_StopTimerThread) return; boost::mutex::scoped_lock lock(l_TimerMutex); m_Started = false; l_Timers.erase(this); /* Notify the worker thread that we've disabled a timer. */ l_TimerCV.notify_all(); while (wait && m_Running) l_TimerCV.wait(lock); }