| Index: base/timer.cc
|
| ===================================================================
|
| --- base/timer.cc (revision 1824)
|
| +++ base/timer.cc (working copy)
|
| @@ -4,218 +4,11 @@
|
|
|
| #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
|
|
|
| void BaseTimer_Helper::OrphanDelayedTask() {
|
|
|