summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authordarin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-12 23:25:43 +0000
committerdarin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-12 23:25:43 +0000
commita5b94a90c11917b9c7f1d91c9a2069badc22819e (patch)
treeb37df6a3cab7423d33ca6d6147fe68ead3a9f844 /base
parent0c6332fe5c874df3fcf1d3b29a6e633efb3418eb (diff)
downloadchromium_src-a5b94a90c11917b9c7f1d91c9a2069badc22819e.zip
chromium_src-a5b94a90c11917b9c7f1d91c9a2069badc22819e.tar.gz
chromium_src-a5b94a90c11917b9c7f1d91c9a2069badc22819e.tar.bz2
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@760 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 9fc2f3e..46fae6e 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 {