blob: ee4a34439d38d80202eb729d6bc39ac6168173b5 [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit3f4a7322008-07-27 06:49:38 +09004
darin@google.com6ddeb842008-08-15 16:31:20 +09005#include "base/message_loop.h"
6
darin@google.com981f3552008-08-16 12:09:05 +09007#include <algorithm>
8
mmentovai@google.comfa5f9932008-08-22 07:26:06 +09009#include "base/compiler_specific.h"
initial.commit3f4a7322008-07-27 06:49:38 +090010#include "base/logging.h"
darin@google.com12d40bb2008-08-20 03:36:23 +090011#include "base/message_pump_default.h"
initial.commit3f4a7322008-07-27 06:49:38 +090012#include "base/string_util.h"
13#include "base/thread_local_storage.h"
initial.commit3f4a7322008-07-27 06:49:38 +090014
15// a TLS index to the message loop for the current thread
16// Note that if we start doing complex stuff in other static initializers
17// this could cause problems.
evanm@google.comf26fd3a2008-08-21 07:54:52 +090018// TODO(evanm): this shouldn't rely on static initialization.
19// static
20TLSSlot MessageLoop::tls_index_;
initial.commit3f4a7322008-07-27 06:49:38 +090021
22//------------------------------------------------------------------------------
23
initial.commit3f4a7322008-07-27 06:49:38 +090024// Logical events for Histogram profiling. Run with -message-loop-histogrammer
25// to get an accounting of messages and actions taken on each thread.
darin@google.com981f3552008-08-16 12:09:05 +090026static const int kTaskRunEvent = 0x1;
27static const int kTimerEvent = 0x2;
initial.commit3f4a7322008-07-27 06:49:38 +090028
29// Provide range of message IDs for use in histogramming and debug display.
30static const int kLeastNonZeroMessageId = 1;
31static const int kMaxMessageId = 1099;
32static const int kNumberOfDistinctMessagesDisplayed = 1100;
33
34//------------------------------------------------------------------------------
35
darin@google.com981f3552008-08-16 12:09:05 +090036#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +090037
initial.commit3f4a7322008-07-27 06:49:38 +090038// Upon a SEH exception in this thread, it restores the original unhandled
39// exception filter.
40static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) {
41 ::SetUnhandledExceptionFilter(old_filter);
42 return EXCEPTION_CONTINUE_SEARCH;
43}
44
45// Retrieves a pointer to the current unhandled exception filter. There
46// is no standalone getter method.
47static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() {
48 LPTOP_LEVEL_EXCEPTION_FILTER top_filter = NULL;
49 top_filter = ::SetUnhandledExceptionFilter(0);
50 ::SetUnhandledExceptionFilter(top_filter);
51 return top_filter;
52}
53
darin@google.com981f3552008-08-16 12:09:05 +090054#endif // defined(OS_WIN)
55
initial.commit3f4a7322008-07-27 06:49:38 +090056//------------------------------------------------------------------------------
57
darin@google.comd936b5b2008-08-26 14:53:57 +090058MessageLoop::MessageLoop(Type type)
59 : type_(type),
darin@google.comee6fa722008-08-13 08:25:43 +090060 nestable_tasks_allowed_(true),
darin@google.com12d40bb2008-08-20 03:36:23 +090061 exception_restoration_(false),
darin@google.combe165ae2008-09-07 17:08:29 +090062 state_(NULL),
63 next_sequence_num_(0) {
darin@google.comd936b5b2008-08-26 14:53:57 +090064 DCHECK(!tls_index_.Get()) << "should only have one message loop per thread";
evanm@google.comf26fd3a2008-08-21 07:54:52 +090065 tls_index_.Set(this);
darin@google.comd936b5b2008-08-26 14:53:57 +090066
darin@google.com132072e2008-08-26 15:52:41 +090067 // TODO(darin): Choose the pump based on the requested type.
darin@google.com981f3552008-08-16 12:09:05 +090068#if defined(OS_WIN)
darin@google.com0795f572008-08-30 09:22:48 +090069 if (type_ == TYPE_DEFAULT) {
70 pump_ = new base::MessagePumpDefault();
71 } else {
72 pump_ = new base::MessagePumpWin();
73 }
darin@google.com12d40bb2008-08-20 03:36:23 +090074#else
darin@google.com132072e2008-08-26 15:52:41 +090075 pump_ = new base::MessagePumpDefault();
darin@google.com981f3552008-08-16 12:09:05 +090076#endif
initial.commit3f4a7322008-07-27 06:49:38 +090077}
78
79MessageLoop::~MessageLoop() {
80 DCHECK(this == current());
darin@google.com965e5342008-08-06 08:16:41 +090081
82 // Let interested parties have one last shot at accessing this.
83 FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_,
84 WillDestroyCurrentMessageLoop());
85
darin@google.com510f6062008-09-09 14:15:56 +090086 // OK, now make it so that no one can find us.
87 tls_index_.Set(NULL);
darin@google.comebe504d2008-09-07 17:52:31 +090088
darin@google.com0e500502008-09-09 14:55:35 +090089 DCHECK(!state_);
90
91 // Most tasks that have not been Run() are deleted in the |timer_manager_|
92 // destructor after we remove our tls index. We delete the tasks in our
93 // queues here so their destuction is similar to the tasks in the
94 // |timer_manager_|.
95 DeletePendingTasks();
96 ReloadWorkQueue();
97 DeletePendingTasks();
98
99 // Delete tasks in the delayed work queue.
100 while (!delayed_work_queue_.empty()) {
101 Task* task = delayed_work_queue_.top().task;
102 delayed_work_queue_.pop();
103 delete task;
104 }
initial.commit3f4a7322008-07-27 06:49:38 +0900105}
106
darin@google.com965e5342008-08-06 08:16:41 +0900107void MessageLoop::AddDestructionObserver(DestructionObserver *obs) {
108 DCHECK(this == current());
109 destruction_observers_.AddObserver(obs);
110}
111
112void MessageLoop::RemoveDestructionObserver(DestructionObserver *obs) {
113 DCHECK(this == current());
114 destruction_observers_.RemoveObserver(obs);
115}
116
darin@google.com6ddeb842008-08-15 16:31:20 +0900117void MessageLoop::Run() {
darin@google.com981f3552008-08-16 12:09:05 +0900118 AutoRunState save_state(this);
119 RunHandler();
darin@google.com6ddeb842008-08-15 16:31:20 +0900120}
121
jar@google.com9239e022008-07-31 22:10:20 +0900122void MessageLoop::RunAllPending() {
darin@google.com981f3552008-08-16 12:09:05 +0900123 AutoRunState save_state(this);
124 state_->quit_received = true; // Means run until we would otherwise block.
125 RunHandler();
initial.commit3f4a7322008-07-27 06:49:38 +0900126}
127
128// Runs the loop in two different SEH modes:
129// enable_SEH_restoration_ = false : any unhandled exception goes to the last
130// one that calls SetUnhandledExceptionFilter().
131// enable_SEH_restoration_ = true : any unhandled exception goes to the filter
132// that was existed before the loop was run.
darin@google.com981f3552008-08-16 12:09:05 +0900133void MessageLoop::RunHandler() {
134#if defined(OS_WIN)
initial.commit3f4a7322008-07-27 06:49:38 +0900135 if (exception_restoration_) {
136 LPTOP_LEVEL_EXCEPTION_FILTER current_filter = GetTopSEHFilter();
137 __try {
darin@google.com981f3552008-08-16 12:09:05 +0900138 RunInternal();
initial.commit3f4a7322008-07-27 06:49:38 +0900139 } __except(SEHFilter(current_filter)) {
140 }
darin@google.com981f3552008-08-16 12:09:05 +0900141 return;
initial.commit3f4a7322008-07-27 06:49:38 +0900142 }
darin@google.com981f3552008-08-16 12:09:05 +0900143#endif
144
145 RunInternal();
initial.commit3f4a7322008-07-27 06:49:38 +0900146}
147
148//------------------------------------------------------------------------------
initial.commit3f4a7322008-07-27 06:49:38 +0900149
darin@google.com981f3552008-08-16 12:09:05 +0900150void MessageLoop::RunInternal() {
151 DCHECK(this == current());
152
initial.commit3f4a7322008-07-27 06:49:38 +0900153 StartHistogrammer();
154
darin@google.com981f3552008-08-16 12:09:05 +0900155#if defined(OS_WIN)
156 if (state_->dispatcher) {
157 pump_win()->RunWithDispatcher(this, state_->dispatcher);
158 return;
jar@google.com9239e022008-07-31 22:10:20 +0900159 }
darin@google.com981f3552008-08-16 12:09:05 +0900160#endif
161
162 pump_->Run(this);
jar@google.comfbaaf692008-07-30 16:50:53 +0900163}
jar@google.com7ff36e62008-07-30 15:58:56 +0900164
jar@google.comb4d1bff2008-07-31 04:03:59 +0900165//------------------------------------------------------------------------------
166// Wrapper functions for use in above message loop framework.
167
initial.commit3f4a7322008-07-27 06:49:38 +0900168bool MessageLoop::ProcessNextDelayedNonNestableTask() {
darin@google.com981f3552008-08-16 12:09:05 +0900169 if (state_->run_depth != 1)
initial.commit3f4a7322008-07-27 06:49:38 +0900170 return false;
171
darin@google.combe165ae2008-09-07 17:08:29 +0900172 if (deferred_non_nestable_work_queue_.empty())
initial.commit3f4a7322008-07-27 06:49:38 +0900173 return false;
darin@google.combe165ae2008-09-07 17:08:29 +0900174
175 Task* task = deferred_non_nestable_work_queue_.front().task;
176 deferred_non_nestable_work_queue_.pop();
177
178 RunTask(task);
initial.commit3f4a7322008-07-27 06:49:38 +0900179 return true;
180}
181
initial.commit3f4a7322008-07-27 06:49:38 +0900182//------------------------------------------------------------------------------
183
184void MessageLoop::Quit() {
darin@google.com981f3552008-08-16 12:09:05 +0900185 DCHECK(current() == this);
186 if (state_) {
187 state_->quit_received = true;
188 } else {
189 NOTREACHED() << "Must be inside Run to call Quit";
initial.commit3f4a7322008-07-27 06:49:38 +0900190 }
initial.commit3f4a7322008-07-27 06:49:38 +0900191}
192
darin@google.combe165ae2008-09-07 17:08:29 +0900193void MessageLoop::PostTask(
194 const tracked_objects::Location& from_here, Task* task) {
195 PostTask_Helper(from_here, task, 0, true);
196}
197
198void MessageLoop::PostDelayedTask(
199 const tracked_objects::Location& from_here, Task* task, int delay_ms) {
200 PostTask_Helper(from_here, task, delay_ms, true);
201}
202
203void MessageLoop::PostNonNestableTask(
204 const tracked_objects::Location& from_here, Task* task) {
205 PostTask_Helper(from_here, task, 0, false);
206}
207
208void MessageLoop::PostNonNestableDelayedTask(
209 const tracked_objects::Location& from_here, Task* task, int delay_ms) {
210 PostTask_Helper(from_here, task, delay_ms, false);
211}
212
initial.commit3f4a7322008-07-27 06:49:38 +0900213// Possibly called on a background thread!
darin@google.combe165ae2008-09-07 17:08:29 +0900214void MessageLoop::PostTask_Helper(
215 const tracked_objects::Location& from_here, Task* task, int delay_ms,
216 bool nestable) {
initial.commit3f4a7322008-07-27 06:49:38 +0900217 task->SetBirthPlace(from_here);
darin@google.com0795f572008-08-30 09:22:48 +0900218
darin@google.combe165ae2008-09-07 17:08:29 +0900219 PendingTask pending_task(task, nestable);
darin@google.com0795f572008-08-30 09:22:48 +0900220
221 if (delay_ms > 0) {
darin@google.combe165ae2008-09-07 17:08:29 +0900222 pending_task.delayed_run_time =
darin@google.com0795f572008-08-30 09:22:48 +0900223 Time::Now() + TimeDelta::FromMilliseconds(delay_ms);
224 } else {
225 DCHECK(delay_ms == 0) << "delay should not be negative";
226 }
227
initial.commit3f4a7322008-07-27 06:49:38 +0900228 // Warning: Don't try to short-circuit, and handle this thread's tasks more
229 // directly, as it could starve handling of foreign threads. Put every task
230 // into this queue.
231
darin@google.com981f3552008-08-16 12:09:05 +0900232 scoped_refptr<base::MessagePump> pump;
initial.commit3f4a7322008-07-27 06:49:38 +0900233 {
darin@google.com981f3552008-08-16 12:09:05 +0900234 AutoLock locked(incoming_queue_lock_);
235
darin@google.combe165ae2008-09-07 17:08:29 +0900236 bool was_empty = incoming_queue_.empty();
237 incoming_queue_.push(pending_task);
initial.commit3f4a7322008-07-27 06:49:38 +0900238 if (!was_empty)
239 return; // Someone else should have started the sub-pump.
240
darin@google.com981f3552008-08-16 12:09:05 +0900241 pump = pump_;
darin@google.com6ddeb842008-08-15 16:31:20 +0900242 }
darin@google.com981f3552008-08-16 12:09:05 +0900243 // Since the incoming_queue_ may contain a task that destroys this message
244 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|.
245 // We use a stack-based reference to the message pump so that we can call
246 // ScheduleWork outside of incoming_queue_lock_.
darin@google.com6ddeb842008-08-15 16:31:20 +0900247
darin@google.com981f3552008-08-16 12:09:05 +0900248 pump->ScheduleWork();
initial.commit3f4a7322008-07-27 06:49:38 +0900249}
250
251void MessageLoop::SetNestableTasksAllowed(bool allowed) {
mpcomplete@google.com989d5f82008-08-09 09:14:09 +0900252 if (nestable_tasks_allowed_ != allowed) {
253 nestable_tasks_allowed_ = allowed;
254 if (!nestable_tasks_allowed_)
255 return;
256 // Start the native pump if we are not already pumping.
darin@google.com981f3552008-08-16 12:09:05 +0900257 pump_->ScheduleWork();
mpcomplete@google.com989d5f82008-08-09 09:14:09 +0900258 }
initial.commit3f4a7322008-07-27 06:49:38 +0900259}
260
261bool MessageLoop::NestableTasksAllowed() const {
262 return nestable_tasks_allowed_;
263}
264
initial.commit3f4a7322008-07-27 06:49:38 +0900265//------------------------------------------------------------------------------
initial.commit3f4a7322008-07-27 06:49:38 +0900266
initial.commit3f4a7322008-07-27 06:49:38 +0900267void MessageLoop::RunTask(Task* task) {
initial.commit3f4a7322008-07-27 06:49:38 +0900268 DCHECK(nestable_tasks_allowed_);
269 // Execute the task and assume the worst: It is probably not reentrant.
270 nestable_tasks_allowed_ = false;
darin@google.combe165ae2008-09-07 17:08:29 +0900271
272 HistogramEvent(kTaskRunEvent);
273 task->Run();
274 delete task;
275
276 nestable_tasks_allowed_ = true;
initial.commit3f4a7322008-07-27 06:49:38 +0900277}
278
darin@google.combe165ae2008-09-07 17:08:29 +0900279bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) {
280 if (pending_task.nestable || state_->run_depth == 1) {
281 RunTask(pending_task.task);
282 // Show that we ran a task (Note: a new one might arrive as a
283 // consequence!).
284 return true;
285 }
286
287 // We couldn't run the task now because we're in a nested message loop
288 // and the task isn't nestable.
289 deferred_non_nestable_work_queue_.push(pending_task);
290 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900291}
292
initial.commit3f4a7322008-07-27 06:49:38 +0900293void MessageLoop::ReloadWorkQueue() {
294 // We can improve performance of our loading tasks from incoming_queue_ to
darin@google.com981f3552008-08-16 12:09:05 +0900295 // work_queue_ by waiting until the last minute (work_queue_ is empty) to
296 // load. That reduces the number of locks-per-task significantly when our
darin@google.combe165ae2008-09-07 17:08:29 +0900297 // queues get large.
298 if (!work_queue_.empty())
initial.commit3f4a7322008-07-27 06:49:38 +0900299 return; // Wait till we *really* need to lock and load.
300
301 // Acquire all we can from the inter-thread queue with one lock acquisition.
initial.commit3f4a7322008-07-27 06:49:38 +0900302 {
303 AutoLock lock(incoming_queue_lock_);
darin@google.combe165ae2008-09-07 17:08:29 +0900304 if (incoming_queue_.empty())
initial.commit3f4a7322008-07-27 06:49:38 +0900305 return;
darin@google.combe165ae2008-09-07 17:08:29 +0900306 std::swap(incoming_queue_, work_queue_);
307 DCHECK(incoming_queue_.empty());
initial.commit3f4a7322008-07-27 06:49:38 +0900308 }
309}
310
darin@google.com0e500502008-09-09 14:55:35 +0900311void MessageLoop::DeletePendingTasks() {
312 /* Comment this out as it's causing crashes.
313 while (!work_queue_.Empty()) {
314 Task* task = work_queue_.Pop();
315 if (task->is_owned_by_message_loop())
316 delete task;
initial.commit3f4a7322008-07-27 06:49:38 +0900317 }
darin@google.com0e500502008-09-09 14:55:35 +0900318
319 while (!delayed_non_nestable_queue_.Empty()) {
320 Task* task = delayed_non_nestable_queue_.Pop();
321 if (task->is_owned_by_message_loop())
322 delete task;
initial.commit3f4a7322008-07-27 06:49:38 +0900323 }
darin@google.com0e500502008-09-09 14:55:35 +0900324 */
initial.commit3f4a7322008-07-27 06:49:38 +0900325}
326
darin@google.com981f3552008-08-16 12:09:05 +0900327bool MessageLoop::DoWork() {
darin@google.combe165ae2008-09-07 17:08:29 +0900328 if (!nestable_tasks_allowed_) {
329 // Task can't be executed right now.
330 return false;
331 }
332
333 for (;;) {
334 ReloadWorkQueue();
335 if (work_queue_.empty())
336 break;
337
338 // Execute oldest task.
339 do {
340 PendingTask pending_task = work_queue_.front();
341 work_queue_.pop();
342 if (!pending_task.delayed_run_time.is_null()) {
343 bool was_empty = delayed_work_queue_.empty();
344
345 // Move to the delayed work queue. Initialize the sequence number
346 // before inserting into the delayed_work_queue_. The sequence number
347 // is used to faciliate FIFO sorting when two tasks have the same
348 // delayed_run_time value.
349 pending_task.sequence_num = next_sequence_num_++;
350 delayed_work_queue_.push(pending_task);
351
352 if (was_empty) // We only schedule the next delayed work item.
353 pump_->ScheduleDelayedWork(pending_task.delayed_run_time);
354 } else {
355 if (DeferOrRunPendingTask(pending_task))
356 return true;
357 }
358 } while (!work_queue_.empty());
359 }
360
361 // Nothing happened.
362 return false;
darin@google.com981f3552008-08-16 12:09:05 +0900363}
364
darin@google.com6393bed2008-08-20 15:30:58 +0900365bool MessageLoop::DoDelayedWork(Time* next_delayed_work_time) {
darin@google.combe165ae2008-09-07 17:08:29 +0900366 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) {
367 *next_delayed_work_time = Time();
368 return false;
369 }
370
371 if (delayed_work_queue_.top().delayed_run_time > Time::Now()) {
372 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
373 return false;
374 }
darin@google.com981f3552008-08-16 12:09:05 +0900375
darin@google.combe165ae2008-09-07 17:08:29 +0900376 PendingTask pending_task = delayed_work_queue_.top();
377 delayed_work_queue_.pop();
378
379 if (!delayed_work_queue_.empty())
380 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
darin@google.com981f3552008-08-16 12:09:05 +0900381
darin@google.combe165ae2008-09-07 17:08:29 +0900382 return DeferOrRunPendingTask(pending_task);
darin@google.com981f3552008-08-16 12:09:05 +0900383}
384
385bool MessageLoop::DoIdleWork() {
386 if (ProcessNextDelayedNonNestableTask())
387 return true;
388
389 if (state_->quit_received)
390 pump_->Quit();
391
392 return false;
393}
394
395//------------------------------------------------------------------------------
396// MessageLoop::AutoRunState
397
398MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) {
399 // Make the loop reference us.
400 previous_state_ = loop_->state_;
401 if (previous_state_) {
402 run_depth = previous_state_->run_depth + 1;
darin@google.com6ddeb842008-08-15 16:31:20 +0900403 } else {
darin@google.com981f3552008-08-16 12:09:05 +0900404 run_depth = 1;
darin@google.com6ddeb842008-08-15 16:31:20 +0900405 }
darin@google.com981f3552008-08-16 12:09:05 +0900406 loop_->state_ = this;
407
408 // Initialize the other fields:
409 quit_received = false;
410#if defined(OS_WIN)
411 dispatcher = NULL;
412#endif
413}
414
415MessageLoop::AutoRunState::~AutoRunState() {
416 loop_->state_ = previous_state_;
darin@google.comee6fa722008-08-13 08:25:43 +0900417}
418
initial.commit3f4a7322008-07-27 06:49:38 +0900419//------------------------------------------------------------------------------
darin@google.combe165ae2008-09-07 17:08:29 +0900420// MessageLoop::PendingTask
initial.commit3f4a7322008-07-27 06:49:38 +0900421
darin@google.combe165ae2008-09-07 17:08:29 +0900422bool MessageLoop::PendingTask::operator<(const PendingTask& other) const {
423 // Since the top of a priority queue is defined as the "greatest" element, we
424 // need to invert the comparison here. We want the smaller time to be at the
425 // top of the heap.
initial.commit3f4a7322008-07-27 06:49:38 +0900426
darin@google.combe165ae2008-09-07 17:08:29 +0900427 if (delayed_run_time < other.delayed_run_time)
428 return false;
initial.commit3f4a7322008-07-27 06:49:38 +0900429
darin@google.combe165ae2008-09-07 17:08:29 +0900430 if (delayed_run_time > other.delayed_run_time)
431 return true;
initial.commit3f4a7322008-07-27 06:49:38 +0900432
darin@google.combe165ae2008-09-07 17:08:29 +0900433 // If the times happen to match, then we use the sequence number to decide.
434 // Compare the difference to support integer roll-over.
435 return (sequence_num - other.sequence_num) > 0;
initial.commit3f4a7322008-07-27 06:49:38 +0900436}
437
438//------------------------------------------------------------------------------
439// Method and data for histogramming events and actions taken by each instance
440// on each thread.
441
442// static
443bool MessageLoop::enable_histogrammer_ = false;
444
445// static
446void MessageLoop::EnableHistogrammer(bool enable) {
447 enable_histogrammer_ = enable;
448}
449
450void MessageLoop::StartHistogrammer() {
451 if (enable_histogrammer_ && !message_histogram_.get()
452 && StatisticsRecorder::WasStarted()) {
darin@google.com981f3552008-08-16 12:09:05 +0900453 DCHECK(!thread_name_.empty());
initial.commit3f4a7322008-07-27 06:49:38 +0900454 message_histogram_.reset(new LinearHistogram(
455 ASCIIToWide("MsgLoop:" + thread_name_).c_str(),
456 kLeastNonZeroMessageId,
457 kMaxMessageId,
458 kNumberOfDistinctMessagesDisplayed));
459 message_histogram_->SetFlags(message_histogram_->kHexRangePrintingFlag);
460 message_histogram_->SetRangeDescriptions(event_descriptions_);
461 }
462}
463
464void MessageLoop::HistogramEvent(int event) {
465 if (message_histogram_.get())
466 message_histogram_->Add(event);
467}
468
initial.commit3f4a7322008-07-27 06:49:38 +0900469// Provide a macro that takes an expression (such as a constant, or macro
470// constant) and creates a pair to initalize an array of pairs. In this case,
471// our pair consists of the expressions value, and the "stringized" version
472// of the expression (i.e., the exrpression put in quotes). For example, if
473// we have:
474// #define FOO 2
475// #define BAR 5
476// then the following:
477// VALUE_TO_NUMBER_AND_NAME(FOO + BAR)
478// will expand to:
479// {7, "FOO + BAR"}
480// We use the resulting array as an argument to our histogram, which reads the
481// number as a bucket identifier, and proceeds to use the corresponding name
482// in the pair (i.e., the quoted string) when printing out a histogram.
483#define VALUE_TO_NUMBER_AND_NAME(name) {name, #name},
484
initial.commit3f4a7322008-07-27 06:49:38 +0900485// static
486const LinearHistogram::DescriptionPair MessageLoop::event_descriptions_[] = {
initial.commit3f4a7322008-07-27 06:49:38 +0900487 // Provide some pretty print capability in our histogram for our internal
488 // messages.
489
initial.commit3f4a7322008-07-27 06:49:38 +0900490 // A few events we handle (kindred to messages), and used to profile actions.
491 VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent)
initial.commit3f4a7322008-07-27 06:49:38 +0900492 VALUE_TO_NUMBER_AND_NAME(kTimerEvent)
493
494 {-1, NULL} // The list must be null terminated, per API to histogram.
495};
license.botf003cfe2008-08-24 09:55:55 +0900496
darin@google.comd936b5b2008-08-26 14:53:57 +0900497//------------------------------------------------------------------------------
498// MessageLoopForUI
499
500#if defined(OS_WIN)
501
502void MessageLoopForUI::Run(Dispatcher* dispatcher) {
503 AutoRunState save_state(this);
504 state_->dispatcher = dispatcher;
505 RunHandler();
506}
507
508void MessageLoopForUI::AddObserver(Observer* observer) {
509 pump_win()->AddObserver(observer);
510}
511
512void MessageLoopForUI::RemoveObserver(Observer* observer) {
513 pump_win()->RemoveObserver(observer);
514}
515
516void MessageLoopForUI::WillProcessMessage(const MSG& message) {
517 pump_win()->WillProcessMessage(message);
518}
519void MessageLoopForUI::DidProcessMessage(const MSG& message) {
520 pump_win()->DidProcessMessage(message);
521}
522void MessageLoopForUI::PumpOutPendingPaintMessages() {
523 pump_win()->PumpOutPendingPaintMessages();
524}
525
526#endif // defined(OS_WIN)
527
528//------------------------------------------------------------------------------
529// MessageLoopForIO
530
531#if defined(OS_WIN)
532
533void MessageLoopForIO::WatchObject(HANDLE object, Watcher* watcher) {
534 pump_win()->WatchObject(object, watcher);
535}
536
537#endif // defined(OS_WIN)