summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authordarin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-12 18:48:07 +0000
committerdarin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-12 18:48:07 +0000
commit5be517218a74dc9e291fb2821e2af9f01fb47e10 (patch)
treea0c4ff49da17d8121a9796523e1da7faa9e2f7c3 /base
parentb4a718ef7d860ccea49e05fa2959790259c8f712 (diff)
downloadchromium_src-5be517218a74dc9e291fb2821e2af9f01fb47e10.zip
chromium_src-5be517218a74dc9e291fb2821e2af9f01fb47e10.tar.gz
chromium_src-5be517218a74dc9e291fb2821e2af9f01fb47e10.tar.bz2
Make timer.cc portable by factoring its Windows bits into MessageLoop.
Please note that the goal of this CL is merely to move the Windowisms out of timer.cc and into message_loop.cc. Next up will be to refactor message_loop.cc so that the Windowisms are further isolated. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@734 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/message_loop.cc78
-rw-r--r--base/message_loop.h5
-rw-r--r--base/timer.cc153
-rw-r--r--base/timer.h114
-rw-r--r--base/timer_unittest.cc3
-rw-r--r--base/tracked_objects.cc2
6 files changed, 158 insertions, 197 deletions
diff --git a/base/message_loop.cc b/base/message_loop.cc
index 5331bc6..18f4448 100644
--- a/base/message_loop.cc
+++ b/base/message_loop.cc
@@ -108,14 +108,17 @@ static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() {
//------------------------------------------------------------------------------
-MessageLoop::MessageLoop() : message_hwnd_(NULL),
- exception_restoration_(false),
- nestable_tasks_allowed_(true),
- dispatcher_(NULL),
- quit_received_(false),
- quit_now_(false),
- task_pump_message_pending_(false),
- run_depth_(0) {
+MessageLoop::MessageLoop()
+#pragma warning(suppress: 4355) // OK, to use |this| in the initializer list.
+ : timer_manager_(this),
+ message_hwnd_(NULL),
+ exception_restoration_(false),
+ nestable_tasks_allowed_(true),
+ dispatcher_(NULL),
+ quit_received_(false),
+ quit_now_(false),
+ task_pump_message_pending_(false),
+ run_depth_(0) {
DCHECK(tls_index_) << "static initializer failed";
DCHECK(!current()) << "should only have one message loop per thread";
ThreadLocalStorage::Set(tls_index_, this);
@@ -406,6 +409,11 @@ LRESULT MessageLoop::WndProc(
return 0;
}
+ case WM_TIMER:
+ ProcessSomeTimers(); // Give the TimerManager a tickle.
+ DidChangeNextTimerExpiry(); // Maybe generate another WM_TIMER.
+ return 0;
+
case kMsgQuit: {
// TODO(jar): bug 1300541 The following assert should be used, but
// currently too much code actually triggers the assert, especially in
@@ -654,21 +662,22 @@ bool MessageLoop::SignalWatcher(size_t object_index) {
bool MessageLoop::RunTimerTask(Timer* timer) {
HistogramEvent(kTimerEvent);
+
Task* task = timer->task();
if (task->is_owned_by_message_loop()) {
- // We constructed it through PostTask().
+ // We constructed it through PostDelayedTask().
DCHECK(!timer->repeating());
timer->set_task(NULL);
delete timer;
task->ResetBirthTime();
return QueueOrRunTask(task);
- } else {
- // This is an unknown timer task, and we *can't* delay running it, as a
- // user might try to cancel it with TimerManager at any moment.
- DCHECK(nestable_tasks_allowed_);
- RunTask(task);
- return true;
}
+
+ // This is an unknown timer task, and we *can't* delay running it, as a user
+ // might try to cancel it with TimerManager at any moment.
+ DCHECK(nestable_tasks_allowed_);
+ RunTask(task);
+ return true;
}
void MessageLoop::DiscardTimer(Timer* timer) {
@@ -823,6 +832,45 @@ void MessageLoop::DeletePendingTasks() {
*/
}
+void MessageLoop::DidChangeNextTimerExpiry() {
+#if defined(OS_WIN)
+ //
+ // We would *like* to provide high resolution timers. Windows timers using
+ // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup
+ // mechanism because the application can enter modal windows loops where it
+ // is not running our MessageLoop; the only way to have our timers fire in
+ // these cases is to post messages there.
+ //
+ // To provide sub-10ms timers, we process timers directly from our run loop.
+ // For the common case, timers will be processed there as the run loop does
+ // its normal work. However, we *also* set the system timer so that WM_TIMER
+ // events fire. This mops up the case of timers not being able to work in
+ // modal message loops. It is possible for the SetTimer to pop and have no
+ // pending timers, because they could have already been processed by the
+ // run loop itself.
+ //
+ // We use a single SetTimer corresponding to the timer that will expire
+ // soonest. As new timers are created and destroyed, we update SetTimer.
+ // Getting a spurrious SetTimer event firing is benign, as we'll just be
+ // processing an empty timer queue.
+ //
+ int delay = timer_manager_.GetCurrentDelay();
+ if (delay == -1) {
+ KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this));
+ } else {
+ if (delay < USER_TIMER_MINIMUM)
+ delay = USER_TIMER_MINIMUM;
+ // Simulates malfunctioning, early firing timers. Pending tasks should only
+ // be invoked when the delay they specify has elapsed.
+ if (timer_manager_.use_broken_delay())
+ delay = 10;
+ // Create a WM_TIMER event that will wake us up to check for any pending
+ // timers (in case we are running within a nested, external sub-pump).
+ SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), delay, NULL);
+ }
+#endif // defined(OS_WIN)
+}
+
//------------------------------------------------------------------------------
// Implementation of the work_queue_ as a ProiritizedTaskQueue
diff --git a/base/message_loop.h b/base/message_loop.h
index 85535b4..81c1e52 100644
--- a/base/message_loop.h
+++ b/base/message_loop.h
@@ -365,6 +365,8 @@ class MessageLoop {
//----------------------------------------------------------------------------
private:
+ friend class TimerManager; // So it can call DidChangeNextTimerExpiry
+
struct ScopedStateSave {
explicit ScopedStateSave(MessageLoop* loop)
: loop_(loop),
@@ -573,6 +575,9 @@ class MessageLoop {
// Post a task to our incomming queue.
void PostTaskInternal(Task* task);
+ // Called by the TimerManager when its next timer changes.
+ void DidChangeNextTimerExpiry();
+
// Start recording histogram info about events and action IF it was enabled
// and IF the statistics recorder can accept a registration of our histogram.
void StartHistogrammer();
diff --git a/base/timer.cc b/base/timer.cc
index 7c3a636..c5e4e87 100644
--- a/base/timer.cc
+++ b/base/timer.cc
@@ -28,52 +28,17 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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"
-// Note about hi-resolution timers.
-// This class would *like* to provide high resolution timers. Windows timers
-// using SetTimer() have a 10ms granularity. We have to use WM_TIMER as a
-// wakeup mechanism because the application can enter modal windows loops where
-// it is not running our MessageLoop; the only way to have our timers fire in
-// these cases is to post messages there.
-//
-// To provide sub-10ms timers, we process timers directly from our main
-// MessageLoop. For the common case, timers will be processed there as the
-// message loop does its normal work. However, we *also* set the system timer
-// so that WM_TIMER events fire. This mops up the case of timers not being
-// able to work in modal message loops. It is possible for the SetTimer to
-// pop and have no pending timers, because they could have already been
-// processed by the message loop itself.
-//
-// We use a single SetTimer corresponding to the timer that will expire
-// soonest. As new timers are created and destroyed, we update SetTimer.
-// Getting a spurrious SetTimer event firing is benign, as we'll just be
-// processing an empty timer queue.
-
-static const wchar_t kWndClass[] = L"Chrome_TimerMessageWindow";
-
-static LRESULT CALLBACK MessageWndProc(HWND hwnd,
- UINT message,
- WPARAM wparam,
- LPARAM lparam) {
- if (message == WM_TIMER) {
- // Timer not firing? Maybe you're suffering from a WM_PAINTstorm. Make sure
- // any WM_PAINT handler you have calls BeginPaint and EndPaint to validate
- // the invalid region, otherwise you will be flooded with paint messages
- // that trump WM_TIMER when PeekMessage is called.
- UINT_PTR timer_id = static_cast<UINT_PTR>(wparam);
- TimerManager* tm = reinterpret_cast<TimerManager*>(timer_id);
- return tm->MessageWndProc(hwnd, message, wparam, lparam);
- }
-
- return DefWindowProc(hwnd, message, wparam, lparam);
-}
-
// A sequence number for all allocated times (used to break ties when
// comparing times in the TimerManager, and assure FIFO execution sequence).
static base::AtomicSequenceNumber timer_id_counter_;
@@ -90,6 +55,14 @@ Timer::Timer(int delay, Task* task, bool repeating)
Reset();
}
+int Timer::GetCurrentDelay() const {
+ // Be careful here. Timers have a precision of microseconds, but this API is
+ // in milliseconds. If there are 5.5ms left, should the delay be 5 or 6? It
+ // should be 6 to avoid timers firing early.
+ double delay = ceil((fire_time_ - Time::Now()).InMillisecondsF());
+ return static_cast<int>(delay);
+}
+
void Timer::Reset() {
creation_time_ = Time::Now();
fire_time_ = creation_time_ + TimeDelta::FromMilliseconds(delay_);
@@ -115,11 +88,10 @@ bool TimerPQueue::ContainsTimer(const Timer* timer) const {
//-----------------------------------------------------------------------------
// TimerManager
-TimerManager::TimerManager()
- : message_hwnd_(NULL),
- use_broken_delay_(false),
- use_native_timers_(true),
- message_loop_(NULL) {
+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
@@ -129,18 +101,14 @@ TimerManager::TimerManager()
// 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);
-
- // Initialize the Message HWND in the constructor so that the window
- // belongs to the same thread as the message loop (this is important!)
- GetMessageHWND();
+#endif
}
TimerManager::~TimerManager() {
+#if defined(OS_WIN)
// Match timeBeginPeriod() from construction.
timeEndPeriod(1);
-
- if (message_hwnd_ != NULL)
- DestroyWindow(message_hwnd_);
+#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()
@@ -168,7 +136,7 @@ void TimerManager::StopTimer(Timer* timer) {
timers_.RemoveTimer(timer);
} else {
timers_.pop();
- UpdateWindowsWmTimer(); // We took away the head of our queue.
+ DidChangeNextTimer();
}
}
@@ -190,7 +158,6 @@ Timer* TimerManager::PeekTopTimer() {
bool TimerManager::RunSomePendingTimers() {
bool did_work = false;
- bool allowed_to_run = message_loop()->NestableTasksAllowed();
// 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.
@@ -203,10 +170,11 @@ bool TimerManager::RunSomePendingTimers() {
// 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() &&
+ if (!message_loop_->NestableTasksAllowed() &&
!pending->task()->is_owned_by_message_loop())
break;
@@ -219,12 +187,12 @@ bool TimerManager::RunSomePendingTimers() {
timers_.push(pending);
}
- message_loop()->RunTimerTask(pending);
+ message_loop_->RunTimerTask(pending);
}
// Restart the WM_TIMER (if necessary).
if (did_work)
- UpdateWindowsWmTimer();
+ DidChangeNextTimer();
return did_work;
}
@@ -239,77 +207,30 @@ void TimerManager::StartTimer(Timer* timer) {
timers_.push(timer); // Priority queue will sort the timer into place.
- if (timers_.top() == timer)
- UpdateWindowsWmTimer(); // We are new head of queue.
-}
-
-void TimerManager::UpdateWindowsWmTimer() {
- if (!use_native_timers_)
- return;
-
- if (timers_.empty()) {
- KillTimer(GetMessageHWND(), reinterpret_cast<UINT_PTR>(this));
- return;
- }
-
- int delay = GetCurrentDelay();
- if (delay < USER_TIMER_MINIMUM)
- delay = USER_TIMER_MINIMUM;
-
- // Simulates malfunctioning, early firing timers. Pending tasks should
- // only be invoked when the delay they specify has elapsed.
- if (use_broken_delay_)
- delay = 10;
-
- // Create a WM_TIMER event that will wake us up to check for any pending
- // timers (in case the message loop was otherwise starving us).
- SetTimer(GetMessageHWND(), reinterpret_cast<UINT_PTR>(this), delay, NULL);
+ if (timers_.top() == timer) // We are new head of queue.
+ DidChangeNextTimer();
}
int TimerManager::GetCurrentDelay() {
if (timers_.empty())
return -1;
- int delay = timers_.top()->current_delay();
+ int delay = timers_.top()->GetCurrentDelay();
if (delay < 0)
delay = 0;
return delay;
}
-int TimerManager::MessageWndProc(HWND hwnd, UINT message, WPARAM wparam,
- LPARAM lparam) {
- DCHECK(!lparam);
- DCHECK(this == message_loop()->timer_manager());
- if (message_loop()->NestableTasksAllowed())
- RunSomePendingTimers();
- else
- UpdateWindowsWmTimer();
- return 0;
-}
-
-MessageLoop* TimerManager::message_loop() {
- if (!message_loop_)
- message_loop_ = MessageLoop::current();
- DCHECK(message_loop_ == MessageLoop::current());
- return message_loop_;
-}
-
-
-HWND TimerManager::GetMessageHWND() {
- if (!message_hwnd_) {
- HINSTANCE hinst = GetModuleHandle(NULL);
-
- WNDCLASSEX wc = {0};
- wc.cbSize = sizeof(wc);
- wc.lpfnWndProc = ::MessageWndProc;
- wc.hInstance = hinst;
- wc.lpszClassName = kWndClass;
- RegisterClassEx(&wc);
-
- message_hwnd_ = CreateWindow(kWndClass, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0,
- hinst, 0);
- DCHECK(message_hwnd_);
+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();
}
- return message_hwnd_;
+ message_loop_->DidChangeNextTimerExpiry();
}
//-----------------------------------------------------------------------------
diff --git a/base/timer.h b/base/timer.h
index de22b64..c23f725 100644
--- a/base/timer.h
+++ b/base/timer.h
@@ -30,54 +30,50 @@
#ifndef BASE_TIMER_H_
#define BASE_TIMER_H_
-#include <math.h>
-
#include <queue>
#include <vector>
#include "base/basictypes.h"
#include "base/time.h"
-#ifdef OS_WIN
-#include <windows.h>
-#endif // OS_WIN
-
+//-----------------------------------------------------------------------------
// Timer/TimerManager are objects designed to help setting timers.
// Goals of TimerManager:
-// - have only one Windows system timer for all app timer functionality
+// - have only one system timer for all app timer functionality
// - work around bugs with timers firing arbitrarily earlier than specified
// - provide the ability to run timers even if the application is in a
// windows modal app loop.
+//-----------------------------------------------------------------------------
+class MessageLoop;
class TimerManager;
class Task;
-class MessageLoop;
+//-----------------------------------------------------------------------------
+// The core timer object. Use TimerManager to create and control timers.
class Timer {
public:
Timer(int delay, Task* task, bool repeating);
+ // The task to be run when the timer fires.
Task* task() const { return task_; }
void set_task(Task* task) { task_ = task; }
- int current_delay() const {
- // Be careful here. Timers have a precision of microseconds,
- // but this API is in milliseconds. If there are 5.5ms left,
- // should the delay be 5 or 6? It should be 6 to avoid timers
- // firing early. Implement ceiling by adding 999us prior to
- // conversion to ms.
- double delay = ceil((fire_time_ - Time::Now()).InMillisecondsF());
- return static_cast<int>(delay);
- }
+ // Returns the time in msec relative to now that the timer should fire.
+ int GetCurrentDelay() const;
+ // Returns the absolute time at which the timer should fire.
const Time &fire_time() const { return fire_time_; }
+ // A repeating timer is a timer that is automatically scheduled to fire again
+ // after it fires.
bool repeating() const { return repeating_; }
// Update (or fill in) creation_time_, and calculate future fire_time_ based
// on current time plus delay_.
void Reset();
+ // A unique identifier for this timer.
int id() const { return timer_id_; }
protected:
@@ -93,9 +89,8 @@ class Timer {
// Timer delay in milliseconds.
int delay_;
- // A monotonically increasing timer id. Used
- // for ordering two timers which have the same
- // timestamp in a FIFO manner.
+ // A monotonically increasing timer id. Used for ordering two timers which
+ // have the same timestamp in a FIFO manner.
int timer_id_;
// Whether or not this timer repeats.
@@ -105,9 +100,11 @@ class Timer {
// iteration started.)
Time creation_time_;
- DISALLOW_EVIL_CONSTRUCTORS(Timer);
+ DISALLOW_COPY_AND_ASSIGN(Timer);
};
+//-----------------------------------------------------------------------------
+// Used to implement TimerPQueue
class TimerComparison {
public:
bool operator() (const Timer* t1, const Timer* t2) const {
@@ -126,14 +123,14 @@ class TimerComparison {
}
};
+//-----------------------------------------------------------------------------
// Subclass priority_queue to provide convenient access to removal from this
// list.
//
// Terminology: The "pending" timer is the timer at the top of the queue,
// i.e. the timer whose task needs to be Run next.
-class TimerPQueue : public std::priority_queue<Timer*,
- std::vector<Timer*>,
- TimerComparison> {
+class TimerPQueue :
+ public std::priority_queue<Timer*, std::vector<Timer*>, TimerComparison> {
public:
// Removes |timer| from the queue.
void RemoveTimer(Timer* timer);
@@ -142,32 +139,26 @@ class TimerPQueue : public std::priority_queue<Timer*,
bool ContainsTimer(const Timer* timer) const;
};
-// There is one TimerManager per thread, owned by the MessageLoop.
-// Timers can either be fired directly by the MessageLoop, or by
-// SetTimer and a WM_TIMER message. The advantage of the former
-// is that we can make timers fire significantly faster than the 10ms
-// granularity provided by SetTimer(). The advantage of SetTimer()
-// is that modal message loops which don't run our MessageLoop
-// code will still be able to process WM_TIMER messages.
+//-----------------------------------------------------------------------------
+// There is one TimerManager per thread, owned by the MessageLoop. Timers can
+// either be fired by the MessageLoop from within its run loop or via a system
+// timer event that the MesssageLoop constructs. The advantage of the former
+// is that we can make timers fire significantly faster than the granularity
+// provided by the system. The advantage of a system timer is that modal
+// message loops which don't run our MessageLoop code will still be able to
+// process system timer events.
//
-// Note: TimerManager is not thread safe. You cannot set timers
-// onto a thread other than your own.
+// NOTE: TimerManager is not thread safe. You cannot set timers onto a thread
+// other than your own.
class TimerManager {
public:
- TimerManager();
+ explicit TimerManager(MessageLoop* message_loop);
~TimerManager();
// Create and start a new timer. |task| is owned by the caller, as is the
// timer object that is returned.
Timer* StartTimer(int delay, Task* task, bool repeating);
- // Flag indicating whether the timer manager should use the OS
- // timers or not. Default is true. MessageLoops which are not reliably
- // called due to nested windows message loops should set this to
- // true.
- bool use_native_timers() { return use_native_timers_; }
- void set_use_native_timers(bool value) { use_native_timers_ = value; }
-
// Starts a timer. This is a no-op if the timer is already started.
void StartTimer(Timer* timer);
@@ -190,15 +181,6 @@ class TimerManager {
// pqueue) needs to be fired. Returns -1 if no timers are pending.
int GetCurrentDelay();
- // A handler for WM_TIMER messages.
- // If a task is not running currently, it runs some timer tasks (if there are
- // some ready to fire), otherwise it just updates the WM_TIMER to be called
- // again (hopefully when it is allowed to run a task).
- int MessageWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
-
- // Return cached copy of MessageLoop::current().
- MessageLoop* message_loop();
-
#ifdef UNIT_TEST
// For testing only, used to simulate broken early-firing WM_TIMER
// notifications by setting arbitrarily small delays in SetTimer.
@@ -207,35 +189,33 @@ class TimerManager {
}
#endif // UNIT_TEST
+ bool use_broken_delay() const {
+ return use_broken_delay_;
+ }
+
protected:
// Peek at the timer which will fire soonest.
Timer* PeekTopTimer();
private:
- // Update our Windows WM_TIMER to match our most immediately pending timer.
- void UpdateWindowsWmTimer();
-
-#ifdef OS_WIN
- // Retrieve the Message Window that handles WM_TIMER messages from the
- // system.
- HWND GetMessageHWND();
+ void DidChangeNextTimer();
- HWND message_hwnd_;
-#endif // OS_WIN
+ // A cached value that indicates the time when we think the next timer is to
+ // fire. We use this to determine if we should call DidChangeNextTimerExpiry
+ // on the MessageLoop.
+ Time next_timer_expiry_;
TimerPQueue timers_;
bool use_broken_delay_;
- // Flag to enable/disable use of native timers.
- bool use_native_timers_;
-
// A lazily cached copy of MessageLoop::current.
MessageLoop* message_loop_;
- DISALLOW_EVIL_CONSTRUCTORS(TimerManager);
+ DISALLOW_COPY_AND_ASSIGN(TimerManager);
};
+//-----------------------------------------------------------------------------
// A simple wrapper for the Timer / TimerManager API. This is a helper class.
// Use OneShotTimer or RepeatingTimer instead.
class SimpleTimer {
@@ -281,9 +261,10 @@ class SimpleTimer {
// we are deallocated. Defaults to true.
bool owns_task_;
- DISALLOW_EVIL_CONSTRUCTORS(SimpleTimer);
+ DISALLOW_COPY_AND_ASSIGN(SimpleTimer);
};
+//-----------------------------------------------------------------------------
// A simple, one-shot timer. The task is run after the specified delay once
// the Start method is called. The task is deleted when the timer object is
// destroyed.
@@ -298,9 +279,10 @@ class OneShotTimer : public SimpleTimer {
: SimpleTimer(delay, task, false) {
}
private:
- DISALLOW_EVIL_CONSTRUCTORS(OneShotTimer);
+ DISALLOW_COPY_AND_ASSIGN(OneShotTimer);
};
+//-----------------------------------------------------------------------------
// A simple, repeating timer. The task is run at the specified interval once
// the Start method is called. The task is deleted when the timer object is
// destroyed.
@@ -315,7 +297,7 @@ class RepeatingTimer : public SimpleTimer {
: SimpleTimer(interval, task, true) {
}
private:
- DISALLOW_EVIL_CONSTRUCTORS(RepeatingTimer);
+ DISALLOW_COPY_AND_ASSIGN(RepeatingTimer);
};
#endif // BASE_TIMER_H_
diff --git a/base/timer_unittest.cc b/base/timer_unittest.cc
index 814836b..4c2593f 100644
--- a/base/timer_unittest.cc
+++ b/base/timer_unittest.cc
@@ -295,6 +295,9 @@ TEST(TimerTest, FifoOrder) {
class MockTimerManager : public TimerManager {
public:
+ MockTimerManager() : TimerManager(MessageLoop::current()) {
+ }
+
// Pops the most-recent to fire timer and returns its timer id.
// Returns -1 if there are no timers in the list.
int pop() {
diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc
index 8694bfd..f94d77b 100644
--- a/base/tracked_objects.cc
+++ b/base/tracked_objects.cc
@@ -29,6 +29,8 @@
#include "base/tracked_objects.h"
+#include <math.h>
+
#include "base/string_util.h"
namespace tracked_objects {