OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_MESSAGE_LOOP_H_ | 5 #ifndef BASE_MESSAGE_LOOP_H_ |
6 #define BASE_MESSAGE_LOOP_H_ | 6 #define BASE_MESSAGE_LOOP_H_ |
7 #pragma once | 7 #pragma once |
8 | 8 |
9 #include <queue> | 9 #include <queue> |
10 #include <string> | 10 #include <string> |
11 | 11 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 // MessageLoop::current()->SetNestableTasksAllowed(true); | 59 // MessageLoop::current()->SetNestableTasksAllowed(true); |
60 // HRESULT hr = DoDragDrop(...); // Implicitly runs a modal message loop here. | 60 // HRESULT hr = DoDragDrop(...); // Implicitly runs a modal message loop here. |
61 // MessageLoop::current()->SetNestableTasksAllowed(old_state); | 61 // MessageLoop::current()->SetNestableTasksAllowed(old_state); |
62 // // Process hr (the result returned by DoDragDrop(). | 62 // // Process hr (the result returned by DoDragDrop(). |
63 // | 63 // |
64 // Please be SURE your task is reentrant (nestable) and all global variables | 64 // Please be SURE your task is reentrant (nestable) and all global variables |
65 // are stable and accessible before calling SetNestableTasksAllowed(true). | 65 // are stable and accessible before calling SetNestableTasksAllowed(true). |
66 // | 66 // |
67 class MessageLoop : public base::MessagePump::Delegate { | 67 class MessageLoop : public base::MessagePump::Delegate { |
68 public: | 68 public: |
69 // A TaskObserver is an object that receives task notifications from the | 69 #if defined(OS_WIN) |
70 // MessageLoop. | 70 typedef base::MessagePumpWin::Dispatcher Dispatcher; |
| 71 typedef base::MessagePumpForUI::Observer Observer; |
| 72 #elif !defined(OS_MACOSX) |
| 73 #if defined(TOUCH_UI) |
| 74 typedef base::MessagePumpGlibXDispatcher Dispatcher; |
| 75 #else |
| 76 typedef base::MessagePumpForUI::Dispatcher Dispatcher; |
| 77 #endif |
| 78 typedef base::MessagePumpForUI::Observer Observer; |
| 79 #endif |
| 80 |
| 81 // A MessageLoop has a particular type, which indicates the set of |
| 82 // asynchronous events it may process in addition to tasks and timers. |
71 // | 83 // |
72 // NOTE: A TaskObserver implementation should be extremely fast! | 84 // TYPE_DEFAULT |
73 class TaskObserver { | 85 // This type of ML only supports tasks and timers. |
74 public: | 86 // |
75 TaskObserver(); | 87 // TYPE_UI |
| 88 // This type of ML also supports native UI events (e.g., Windows messages). |
| 89 // See also MessageLoopForUI. |
| 90 // |
| 91 // TYPE_IO |
| 92 // This type of ML also supports asynchronous IO. See also |
| 93 // MessageLoopForIO. |
| 94 // |
| 95 enum Type { |
| 96 TYPE_DEFAULT, |
| 97 TYPE_UI, |
| 98 TYPE_IO |
| 99 }; |
76 | 100 |
77 // This method is called before processing a task. | 101 // Normally, it is not necessary to instantiate a MessageLoop. Instead, it |
78 virtual void WillProcessTask(const Task* task) = 0; | 102 // is typical to make use of the current thread's MessageLoop instance. |
79 | 103 explicit MessageLoop(Type type = TYPE_DEFAULT); |
80 // This method is called after processing a task. | 104 ~MessageLoop(); |
81 virtual void DidProcessTask(const Task* task) = 0; | |
82 | |
83 protected: | |
84 virtual ~TaskObserver(); | |
85 }; | |
86 | 105 |
87 static void EnableHistogrammer(bool enable_histogrammer); | 106 static void EnableHistogrammer(bool enable_histogrammer); |
88 | 107 |
89 // A DestructionObserver is notified when the current MessageLoop is being | 108 // A DestructionObserver is notified when the current MessageLoop is being |
90 // destroyed. These obsevers are notified prior to MessageLoop::current() | 109 // destroyed. These obsevers are notified prior to MessageLoop::current() |
91 // being changed to return NULL. This gives interested parties the chance to | 110 // being changed to return NULL. This gives interested parties the chance to |
92 // do final cleanup that depends on the MessageLoop. | 111 // do final cleanup that depends on the MessageLoop. |
93 // | 112 // |
94 // NOTE: Any tasks posted to the MessageLoop during this notification will | 113 // NOTE: Any tasks posted to the MessageLoop during this notification will |
95 // not be run. Instead, they will be deleted. | 114 // not be run. Instead, they will be deleted. |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 | 212 |
194 // Invokes Quit on the current MessageLoop when run. Useful to schedule an | 213 // Invokes Quit on the current MessageLoop when run. Useful to schedule an |
195 // arbitrary MessageLoop to Quit. | 214 // arbitrary MessageLoop to Quit. |
196 class QuitTask : public Task { | 215 class QuitTask : public Task { |
197 public: | 216 public: |
198 virtual void Run() { | 217 virtual void Run() { |
199 MessageLoop::current()->Quit(); | 218 MessageLoop::current()->Quit(); |
200 } | 219 } |
201 }; | 220 }; |
202 | 221 |
203 // A MessageLoop has a particular type, which indicates the set of | |
204 // asynchronous events it may process in addition to tasks and timers. | |
205 // | |
206 // TYPE_DEFAULT | |
207 // This type of ML only supports tasks and timers. | |
208 // | |
209 // TYPE_UI | |
210 // This type of ML also supports native UI events (e.g., Windows messages). | |
211 // See also MessageLoopForUI. | |
212 // | |
213 // TYPE_IO | |
214 // This type of ML also supports asynchronous IO. See also | |
215 // MessageLoopForIO. | |
216 // | |
217 enum Type { | |
218 TYPE_DEFAULT, | |
219 TYPE_UI, | |
220 TYPE_IO | |
221 }; | |
222 | |
223 // Normally, it is not necessary to instantiate a MessageLoop. Instead, it | |
224 // is typical to make use of the current thread's MessageLoop instance. | |
225 explicit MessageLoop(Type type = TYPE_DEFAULT); | |
226 ~MessageLoop(); | |
227 | |
228 // Returns the type passed to the constructor. | 222 // Returns the type passed to the constructor. |
229 Type type() const { return type_; } | 223 Type type() const { return type_; } |
230 | 224 |
231 // Optional call to connect the thread name with this loop. | 225 // Optional call to connect the thread name with this loop. |
232 void set_thread_name(const std::string& thread_name) { | 226 void set_thread_name(const std::string& thread_name) { |
233 DCHECK(thread_name_.empty()) << "Should not rename this thread!"; | 227 DCHECK(thread_name_.empty()) << "Should not rename this thread!"; |
234 thread_name_ = thread_name; | 228 thread_name_ = thread_name; |
235 } | 229 } |
236 const std::string& thread_name() const { return thread_name_; } | 230 const std::string& thread_name() const { return thread_name_; } |
237 | 231 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 // exception filter that was active when Run() was called. This can happen | 271 // exception filter that was active when Run() was called. This can happen |
278 // if some third party code call SetUnhandledExceptionFilter() and never | 272 // if some third party code call SetUnhandledExceptionFilter() and never |
279 // restores the previous filter. | 273 // restores the previous filter. |
280 void set_exception_restoration(bool restore) { | 274 void set_exception_restoration(bool restore) { |
281 exception_restoration_ = restore; | 275 exception_restoration_ = restore; |
282 } | 276 } |
283 | 277 |
284 // Returns true if we are currently running a nested message loop. | 278 // Returns true if we are currently running a nested message loop. |
285 bool IsNested(); | 279 bool IsNested(); |
286 | 280 |
| 281 // A TaskObserver is an object that receives task notifications from the |
| 282 // MessageLoop. |
| 283 // |
| 284 // NOTE: A TaskObserver implementation should be extremely fast! |
| 285 class TaskObserver { |
| 286 public: |
| 287 TaskObserver(); |
| 288 |
| 289 // This method is called before processing a task. |
| 290 virtual void WillProcessTask(const Task* task) = 0; |
| 291 |
| 292 // This method is called after processing a task. |
| 293 virtual void DidProcessTask(const Task* task) = 0; |
| 294 |
| 295 protected: |
| 296 virtual ~TaskObserver(); |
| 297 }; |
| 298 |
287 // These functions can only be called on the same thread that |this| is | 299 // These functions can only be called on the same thread that |this| is |
288 // running on. | 300 // running on. |
289 void AddTaskObserver(TaskObserver* task_observer); | 301 void AddTaskObserver(TaskObserver* task_observer); |
290 void RemoveTaskObserver(TaskObserver* task_observer); | 302 void RemoveTaskObserver(TaskObserver* task_observer); |
291 | 303 |
292 #if defined(OS_WIN) | |
293 typedef base::MessagePumpWin::Dispatcher Dispatcher; | |
294 typedef base::MessagePumpForUI::Observer Observer; | |
295 #elif !defined(OS_MACOSX) | |
296 #if defined(TOUCH_UI) | |
297 typedef base::MessagePumpGlibXDispatcher Dispatcher; | |
298 #else | |
299 typedef base::MessagePumpForUI::Dispatcher Dispatcher; | |
300 #endif | |
301 typedef base::MessagePumpForUI::Observer Observer; | |
302 #endif | |
303 | |
304 // Returns true if the message loop has high resolution timers enabled. | 304 // Returns true if the message loop has high resolution timers enabled. |
305 // Provided for testing. | 305 // Provided for testing. |
306 bool high_resolution_timers_enabled() { | 306 bool high_resolution_timers_enabled() { |
307 #if defined(OS_WIN) | 307 #if defined(OS_WIN) |
308 return !high_resolution_timer_expiration_.is_null(); | 308 return !high_resolution_timer_expiration_.is_null(); |
309 #else | 309 #else |
310 return true; | 310 return true; |
311 #endif | 311 #endif |
312 } | 312 } |
313 | 313 |
(...skipping 20 matching lines...) Expand all Loading... |
334 public: | 334 public: |
335 explicit AutoRunState(MessageLoop* loop); | 335 explicit AutoRunState(MessageLoop* loop); |
336 ~AutoRunState(); | 336 ~AutoRunState(); |
337 private: | 337 private: |
338 MessageLoop* loop_; | 338 MessageLoop* loop_; |
339 RunState* previous_state_; | 339 RunState* previous_state_; |
340 }; | 340 }; |
341 | 341 |
342 // This structure is copied around by value. | 342 // This structure is copied around by value. |
343 struct PendingTask { | 343 struct PendingTask { |
344 Task* task; // The task to run. | |
345 base::TimeTicks delayed_run_time; // The time when the task should be run. | |
346 int sequence_num; // Secondary sort key for run time. | |
347 bool nestable; // OK to dispatch from a nested loop. | |
348 | |
349 PendingTask(Task* task, bool nestable) | 344 PendingTask(Task* task, bool nestable) |
350 : task(task), sequence_num(0), nestable(nestable) { | 345 : task(task), sequence_num(0), nestable(nestable) { |
351 } | 346 } |
352 | 347 |
353 // Used to support sorting. | 348 // Used to support sorting. |
354 bool operator<(const PendingTask& other) const; | 349 bool operator<(const PendingTask& other) const; |
| 350 |
| 351 Task* task; // The task to run. |
| 352 base::TimeTicks delayed_run_time; // The time when the task should be run. |
| 353 int sequence_num; // Secondary sort key for run time. |
| 354 bool nestable; // OK to dispatch from a nested loop. |
355 }; | 355 }; |
356 | 356 |
357 class TaskQueue : public std::queue<PendingTask> { | 357 class TaskQueue : public std::queue<PendingTask> { |
358 public: | 358 public: |
359 void Swap(TaskQueue* queue) { | 359 void Swap(TaskQueue* queue) { |
360 c.swap(queue->c); // Calls std::deque::swap | 360 c.swap(queue->c); // Calls std::deque::swap |
361 } | 361 } |
362 }; | 362 }; |
363 | 363 |
364 typedef std::priority_queue<PendingTask> DelayedTaskQueue; | 364 typedef std::priority_queue<PendingTask> DelayedTaskQueue; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 | 420 |
421 // Delete tasks that haven't run yet without running them. Used in the | 421 // Delete tasks that haven't run yet without running them. Used in the |
422 // destructor to make sure all the task's destructors get called. Returns | 422 // destructor to make sure all the task's destructors get called. Returns |
423 // true if some work was done. | 423 // true if some work was done. |
424 bool DeletePendingTasks(); | 424 bool DeletePendingTasks(); |
425 | 425 |
426 // Post a task to our incomming queue. | 426 // Post a task to our incomming queue. |
427 void PostTask_Helper(const tracked_objects::Location& from_here, Task* task, | 427 void PostTask_Helper(const tracked_objects::Location& from_here, Task* task, |
428 int64 delay_ms, bool nestable); | 428 int64 delay_ms, bool nestable); |
429 | 429 |
430 // base::MessagePump::Delegate methods: | |
431 virtual bool DoWork(); | |
432 virtual bool DoDelayedWork(base::TimeTicks* next_delayed_work_time); | |
433 virtual bool DoIdleWork(); | |
434 | |
435 // Start recording histogram info about events and action IF it was enabled | 430 // Start recording histogram info about events and action IF it was enabled |
436 // and IF the statistics recorder can accept a registration of our histogram. | 431 // and IF the statistics recorder can accept a registration of our histogram. |
437 void StartHistogrammer(); | 432 void StartHistogrammer(); |
438 | 433 |
439 // Add occurence of event to our histogram, so that we can see what is being | 434 // Add occurence of event to our histogram, so that we can see what is being |
440 // done in a specific MessageLoop instance (i.e., specific thread). | 435 // done in a specific MessageLoop instance (i.e., specific thread). |
441 // If message_histogram_ is NULL, this is a no-op. | 436 // If message_histogram_ is NULL, this is a no-op. |
442 void HistogramEvent(int event); | 437 void HistogramEvent(int event); |
443 | 438 |
| 439 // base::MessagePump::Delegate methods: |
| 440 virtual bool DoWork(); |
| 441 virtual bool DoDelayedWork(base::TimeTicks* next_delayed_work_time); |
| 442 virtual bool DoIdleWork(); |
| 443 |
444 Type type_; | 444 Type type_; |
445 | 445 |
446 // A list of tasks that need to be processed by this instance. Note that | 446 // A list of tasks that need to be processed by this instance. Note that |
447 // this queue is only accessed (push/pop) by our current thread. | 447 // this queue is only accessed (push/pop) by our current thread. |
448 TaskQueue work_queue_; | 448 TaskQueue work_queue_; |
449 | 449 |
450 // Contains delayed tasks, sorted by their 'delayed_run_time' property. | 450 // Contains delayed tasks, sorted by their 'delayed_run_time' property. |
451 DelayedTaskQueue delayed_work_queue_; | 451 DelayedTaskQueue delayed_work_queue_; |
452 | 452 |
453 // A recent snapshot of Time::Now(), used to check delayed_work_queue_. | 453 // A recent snapshot of Time::Now(), used to check delayed_work_queue_. |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 #endif // defined(OS_POSIX) | 609 #endif // defined(OS_POSIX) |
610 }; | 610 }; |
611 | 611 |
612 // Do not add any member variables to MessageLoopForIO! This is important b/c | 612 // Do not add any member variables to MessageLoopForIO! This is important b/c |
613 // MessageLoopForIO is often allocated via MessageLoop(TYPE_IO). Any extra | 613 // MessageLoopForIO is often allocated via MessageLoop(TYPE_IO). Any extra |
614 // data that you need should be stored on the MessageLoop's pump_ instance. | 614 // data that you need should be stored on the MessageLoop's pump_ instance. |
615 COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO), | 615 COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO), |
616 MessageLoopForIO_should_not_have_extra_member_variables); | 616 MessageLoopForIO_should_not_have_extra_member_variables); |
617 | 617 |
618 #endif // BASE_MESSAGE_LOOP_H_ | 618 #endif // BASE_MESSAGE_LOOP_H_ |
OLD | NEW |