diff options
Diffstat (limited to 'base/timer.cc')
-rw-r--r-- | base/timer.cc | 207 |
1 files changed, 0 insertions, 207 deletions
diff --git a/base/timer.cc b/base/timer.cc index 9f6e7b0..7fac059 100644 --- a/base/timer.cc +++ b/base/timer.cc @@ -4,217 +4,10 @@ #include "base/timer.h" -#include <math.h> -#if defined(OS_WIN) -#include <mmsystem.h> -#endif - -#include "base/atomic_sequence_num.h" -#include "base/logging.h" #include "base/message_loop.h" -#include "base/task.h" namespace base { -// A sequence number for all allocated times (used to break ties when -// comparing times in the TimerManager, and assure FIFO execution sequence). -static AtomicSequenceNumber timer_id_counter_(base::LINKER_INITIALIZED); - -//----------------------------------------------------------------------------- -// Timer - -Timer::Timer(int delay, Task* task, bool repeating) - : task_(task), - delay_(delay), - repeating_(repeating) { - timer_id_ = timer_id_counter_.GetNext(); - DCHECK(delay >= 0); - Reset(); -} - -Timer::Timer(Time fire_time, Task* task) - : fire_time_(fire_time), - task_(task), - repeating_(false) { - timer_id_ = timer_id_counter_.GetNext(); - - // TODO(darin): kill off this stuff. because we are forced to compute 'now' - // in order to determine the delay, it is possible that our fire time could - // be in the past. /sigh/ - creation_time_ = Time::Now(); - delay_ = static_cast<int>((fire_time_ - creation_time_).InMilliseconds()); - if (delay_ < 0) - delay_ = 0; -} - -void Timer::Reset() { - creation_time_ = Time::Now(); - fire_time_ = creation_time_ + TimeDelta::FromMilliseconds(delay_); - DHISTOGRAM_COUNTS(L"Timer.Durations", delay_); -} - -//----------------------------------------------------------------------------- -// TimerPQueue - -void TimerPQueue::RemoveTimer(Timer* timer) { - const std::vector<Timer*>::iterator location = - find(c.begin(), c.end(), timer); - if (location != c.end()) { - c.erase(location); - make_heap(c.begin(), c.end(), TimerComparison()); - } -} - -bool TimerPQueue::ContainsTimer(const Timer* timer) const { - return find(c.begin(), c.end(), timer) != c.end(); -} - -//----------------------------------------------------------------------------- -// TimerManager - -TimerManager::TimerManager(MessageLoop* message_loop) - : use_broken_delay_(false), - message_loop_(message_loop) { -#if defined(OS_WIN) - // We've experimented with all sorts of timers, and initially tried - // to avoid using timeBeginPeriod because it does affect the system - // globally. However, after much investigation, it turns out that all - // of the major plugins (flash, windows media 9-11, and quicktime) - // already use timeBeginPeriod to increase the speed of the clock. - // Since the browser must work with these plugins, the browser already - // needs to support a fast clock. We may as well use this ourselves, - // as it really is the best timer mechanism for our needs. - timeBeginPeriod(1); -#endif -} - -TimerManager::~TimerManager() { -#if defined(OS_WIN) - // Match timeBeginPeriod() from construction. - timeEndPeriod(1); -#endif - - // Be nice to unit tests, and discard and delete all timers along with the - // embedded task objects by handing off to MessageLoop (which would have Run() - // and optionally deleted the objects). - while (timers_.size()) { - Timer* pending = timers_.top(); - timers_.pop(); - message_loop_->DiscardTimer(pending); - } -} - - -Timer* TimerManager::StartTimer(int delay, Task* task, bool repeating) { - Timer* t = new Timer(delay, task, repeating); - StartTimer(t); - return t; -} - -void TimerManager::StopTimer(Timer* timer) { - // Make sure the timer is actually running. - if (!IsTimerRunning(timer)) - return; - // Kill the active timer, and remove the pending entry from the queue. - if (timer != timers_.top()) { - timers_.RemoveTimer(timer); - } else { - timers_.pop(); - DidChangeNextTimer(); - } -} - -void TimerManager::ResetTimer(Timer* timer) { - StopTimer(timer); - timer->Reset(); - StartTimer(timer); -} - -bool TimerManager::IsTimerRunning(const Timer* timer) const { - return timers_.ContainsTimer(timer); -} - -Timer* TimerManager::PeekTopTimer() { - if (timers_.empty()) - return NULL; - return timers_.top(); -} - -bool TimerManager::RunSomePendingTimers() { - bool did_work = false; - // Process a small group of timers. Cap the maximum number of timers we can - // process so we don't deny cycles to other parts of the process when lots of - // timers have been set. - const int kMaxTimersPerCall = 2; - for (int i = 0; i < kMaxTimersPerCall; ++i) { - if (timers_.empty() || timers_.top()->fire_time() > Time::Now()) - break; - - // Get a pending timer. Deal with updating the timers_ queue and setting - // the TopTimer. We'll execute the timer task only after the timer queue - // is back in a consistent state. - Timer* pending = timers_.top(); - - // If pending task isn't invoked_later, then it must be possible to run it - // now (i.e., current task needs to be reentrant). - // TODO(jar): We may block tasks that we can queue from being popped. - if (!message_loop_->NestableTasksAllowed() && - !pending->task()->owned_by_message_loop_) - break; - - timers_.pop(); - did_work = true; - - // If the timer is repeating, add it back to the list of timers to process. - if (pending->repeating()) { - pending->Reset(); - timers_.push(pending); - } - - message_loop_->RunTimerTask(pending); - } - - // Restart the WM_TIMER (if necessary). - if (did_work) - DidChangeNextTimer(); - - return did_work; -} - -// Note: Caller is required to call timer->Reset() before calling StartTimer(). -// TODO(jar): change API so that Reset() is called as part of StartTimer, making -// the API a little less error prone. -void TimerManager::StartTimer(Timer* timer) { - // Make sure the timer is not running. - if (IsTimerRunning(timer)) - return; - - timers_.push(timer); // Priority queue will sort the timer into place. - - if (timers_.top() == timer) // We are new head of queue. - DidChangeNextTimer(); -} - -Time TimerManager::GetNextFireTime() const { - if (timers_.empty()) - return Time(); - - return timers_.top()->fire_time(); -} - -void TimerManager::DidChangeNextTimer() { - // Determine if the next timer expiry actually changed... - if (!timers_.empty()) { - const Time& expiry = timers_.top()->fire_time(); - if (expiry == next_timer_expiry_) - return; - next_timer_expiry_ = expiry; - } else { - next_timer_expiry_ = Time(); - } - message_loop_->DidChangeNextTimerExpiry(); -} - //----------------------------------------------------------------------------- // BaseTimer_Helper |