OLD | NEW |
1 // Copyright (c) 2011 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 |
12 #include "base/base_export.h" | 12 #include "base/base_export.h" |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/callback.h" | 14 #include "base/callback.h" |
15 #include "base/location.h" | 15 #include "base/location.h" |
16 #include "base/memory/ref_counted.h" | 16 #include "base/memory/ref_counted.h" |
17 #include "base/message_loop_proxy.h" | 17 #include "base/message_loop_proxy.h" |
18 #include "base/message_pump.h" | 18 #include "base/message_pump.h" |
19 #include "base/observer_list.h" | 19 #include "base/observer_list.h" |
| 20 #include "base/pending_task.h" |
20 #include "base/synchronization/lock.h" | 21 #include "base/synchronization/lock.h" |
21 #include "base/task.h" | 22 #include "base/task.h" |
22 #include "base/tracking_info.h" | 23 #include "base/tracking_info.h" |
23 #include "base/time.h" | 24 #include "base/time.h" |
24 | 25 |
25 #if defined(OS_WIN) | 26 #if defined(OS_WIN) |
26 // We need this to declare base::MessagePumpWin::Dispatcher, which we should | 27 // We need this to declare base::MessagePumpWin::Dispatcher, which we should |
27 // really just eliminate. | 28 // really just eliminate. |
28 #include "base/message_pump_win.h" | 29 #include "base/message_pump_win.h" |
29 #elif defined(OS_POSIX) | 30 #elif defined(OS_POSIX) |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 static MessageLoop* current(); | 115 static MessageLoop* current(); |
115 | 116 |
116 static void EnableHistogrammer(bool enable_histogrammer); | 117 static void EnableHistogrammer(bool enable_histogrammer); |
117 | 118 |
118 typedef base::MessagePump* (MessagePumpFactory)(); | 119 typedef base::MessagePump* (MessagePumpFactory)(); |
119 // Using the given base::MessagePumpForUIFactory to override the default | 120 // Using the given base::MessagePumpForUIFactory to override the default |
120 // MessagePump implementation for 'TYPE_UI'. | 121 // MessagePump implementation for 'TYPE_UI'. |
121 static void InitMessagePumpForUIFactory(MessagePumpFactory* factory); | 122 static void InitMessagePumpForUIFactory(MessagePumpFactory* factory); |
122 | 123 |
123 // A DestructionObserver is notified when the current MessageLoop is being | 124 // A DestructionObserver is notified when the current MessageLoop is being |
124 // destroyed. These obsevers are notified prior to MessageLoop::current() | 125 // destroyed. These observers are notified prior to MessageLoop::current() |
125 // being changed to return NULL. This gives interested parties the chance to | 126 // being changed to return NULL. This gives interested parties the chance to |
126 // do final cleanup that depends on the MessageLoop. | 127 // do final cleanup that depends on the MessageLoop. |
127 // | 128 // |
128 // NOTE: Any tasks posted to the MessageLoop during this notification will | 129 // NOTE: Any tasks posted to the MessageLoop during this notification will |
129 // not be run. Instead, they will be deleted. | 130 // not be run. Instead, they will be deleted. |
130 // | 131 // |
131 class BASE_EXPORT DestructionObserver { | 132 class BASE_EXPORT DestructionObserver { |
132 public: | 133 public: |
133 virtual void WillDestroyCurrentMessageLoop() = 0; | 134 virtual void WillDestroyCurrentMessageLoop() = 0; |
134 | 135 |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 bool os_modal_loop() const { | 371 bool os_modal_loop() const { |
371 return os_modal_loop_; | 372 return os_modal_loop_; |
372 } | 373 } |
373 #endif // OS_WIN | 374 #endif // OS_WIN |
374 | 375 |
375 // Can only be called from the thread that owns the MessageLoop. | 376 // Can only be called from the thread that owns the MessageLoop. |
376 bool is_running() const; | 377 bool is_running() const; |
377 | 378 |
378 //---------------------------------------------------------------------------- | 379 //---------------------------------------------------------------------------- |
379 protected: | 380 protected: |
| 381 // PendingTasks are sorted by their |delayed_run_time| property. |
| 382 typedef std::priority_queue<base::PendingTask> DelayedTaskQueue; |
| 383 |
380 struct RunState { | 384 struct RunState { |
381 // Used to count how many Run() invocations are on the stack. | 385 // Used to count how many Run() invocations are on the stack. |
382 int run_depth; | 386 int run_depth; |
383 | 387 |
384 // Used to record that Quit() was called, or that we should quit the pump | 388 // Used to record that Quit() was called, or that we should quit the pump |
385 // once it becomes idle. | 389 // once it becomes idle. |
386 bool quit_received; | 390 bool quit_received; |
387 | 391 |
388 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) | 392 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) |
389 Dispatcher* dispatcher; | 393 Dispatcher* dispatcher; |
(...skipping 10 matching lines...) Expand all Loading... |
400 explicit AutoRunState(MessageLoop* loop); | 404 explicit AutoRunState(MessageLoop* loop); |
401 ~AutoRunState(); | 405 ~AutoRunState(); |
402 private: | 406 private: |
403 MessageLoop* loop_; | 407 MessageLoop* loop_; |
404 RunState* previous_state_; | 408 RunState* previous_state_; |
405 }; | 409 }; |
406 #if defined(OS_ANDROID) | 410 #if defined(OS_ANDROID) |
407 protected: | 411 protected: |
408 #endif | 412 #endif |
409 | 413 |
410 // This structure is copied around by value. | |
411 struct PendingTask : public base::TrackingInfo { | |
412 PendingTask(const base::Closure& task, | |
413 const tracked_objects::Location& posted_from, | |
414 base::TimeTicks delayed_run_time, | |
415 bool nestable); | |
416 ~PendingTask(); | |
417 | |
418 // Used to support sorting. | |
419 bool operator<(const PendingTask& other) const; | |
420 | |
421 // The task to run. | |
422 base::Closure task; | |
423 | |
424 // The site this PendingTask was posted from. | |
425 tracked_objects::Location posted_from; | |
426 | |
427 // Secondary sort key for run time. | |
428 int sequence_num; | |
429 | |
430 // OK to dispatch from a nested loop. | |
431 bool nestable; | |
432 }; | |
433 | |
434 class TaskQueue : public std::queue<PendingTask> { | |
435 public: | |
436 void Swap(TaskQueue* queue) { | |
437 c.swap(queue->c); // Calls std::deque::swap | |
438 } | |
439 }; | |
440 | |
441 typedef std::priority_queue<PendingTask> DelayedTaskQueue; | |
442 | |
443 #if defined(OS_WIN) | 414 #if defined(OS_WIN) |
444 base::MessagePumpWin* pump_win() { | 415 base::MessagePumpWin* pump_win() { |
445 return static_cast<base::MessagePumpWin*>(pump_.get()); | 416 return static_cast<base::MessagePumpWin*>(pump_.get()); |
446 } | 417 } |
447 #elif defined(OS_POSIX) | 418 #elif defined(OS_POSIX) |
448 base::MessagePumpLibevent* pump_libevent() { | 419 base::MessagePumpLibevent* pump_libevent() { |
449 return static_cast<base::MessagePumpLibevent*>(pump_.get()); | 420 return static_cast<base::MessagePumpLibevent*>(pump_.get()); |
450 } | 421 } |
451 #endif | 422 #endif |
452 | 423 |
453 // A function to encapsulate all the exception handling capability in the | 424 // A function to encapsulate all the exception handling capability in the |
454 // stacks around the running of a main message loop. It will run the message | 425 // stacks around the running of a main message loop. It will run the message |
455 // loop in a SEH try block or not depending on the set_SEH_restoration() | 426 // loop in a SEH try block or not depending on the set_SEH_restoration() |
456 // flag invoking respectively RunInternalInSEHFrame() or RunInternal(). | 427 // flag invoking respectively RunInternalInSEHFrame() or RunInternal(). |
457 void RunHandler(); | 428 void RunHandler(); |
458 | 429 |
459 #if defined(OS_WIN) | 430 #if defined(OS_WIN) |
460 __declspec(noinline) void RunInternalInSEHFrame(); | 431 __declspec(noinline) void RunInternalInSEHFrame(); |
461 #endif | 432 #endif |
462 | 433 |
463 // A surrounding stack frame around the running of the message loop that | 434 // A surrounding stack frame around the running of the message loop that |
464 // supports all saving and restoring of state, as is needed for any/all (ugly) | 435 // supports all saving and restoring of state, as is needed for any/all (ugly) |
465 // recursive calls. | 436 // recursive calls. |
466 void RunInternal(); | 437 void RunInternal(); |
467 | 438 |
468 // Called to process any delayed non-nestable tasks. | 439 // Called to process any delayed non-nestable tasks. |
469 bool ProcessNextDelayedNonNestableTask(); | 440 bool ProcessNextDelayedNonNestableTask(); |
470 | 441 |
471 // Runs the specified PendingTask. | 442 // Runs the specified PendingTask. |
472 void RunTask(const PendingTask& pending_task); | 443 void RunTask(const base::PendingTask& pending_task); |
473 | 444 |
474 // Calls RunTask or queues the pending_task on the deferred task list if it | 445 // Calls RunTask or queues the pending_task on the deferred task list if it |
475 // cannot be run right now. Returns true if the task was run. | 446 // cannot be run right now. Returns true if the task was run. |
476 bool DeferOrRunPendingTask(const PendingTask& pending_task); | 447 bool DeferOrRunPendingTask(const base::PendingTask& pending_task); |
477 | 448 |
478 // Adds the pending task to delayed_work_queue_. | 449 // Adds the pending task to delayed_work_queue_. |
479 void AddToDelayedWorkQueue(const PendingTask& pending_task); | 450 void AddToDelayedWorkQueue(const base::PendingTask& pending_task); |
480 | 451 |
481 // Adds the pending task to our incoming_queue_. | 452 // Adds the pending task to our incoming_queue_. |
482 // | 453 // |
483 // Caller retains ownership of |pending_task|, but this function will | 454 // Caller retains ownership of |pending_task|, but this function will |
484 // reset the value of pending_task->task. This is needed to ensure | 455 // reset the value of pending_task->task. This is needed to ensure |
485 // that the posting call stack does not retain pending_task->task | 456 // that the posting call stack does not retain pending_task->task |
486 // beyond this function call. | 457 // beyond this function call. |
487 void AddToIncomingQueue(PendingTask* pending_task); | 458 void AddToIncomingQueue(base::PendingTask* pending_task); |
488 | 459 |
489 // Load tasks from the incoming_queue_ into work_queue_ if the latter is | 460 // Load tasks from the incoming_queue_ into work_queue_ if the latter is |
490 // empty. The former requires a lock to access, while the latter is directly | 461 // empty. The former requires a lock to access, while the latter is directly |
491 // accessible on this thread. | 462 // accessible on this thread. |
492 void ReloadWorkQueue(); | 463 void ReloadWorkQueue(); |
493 | 464 |
494 // Delete tasks that haven't run yet without running them. Used in the | 465 // Delete tasks that haven't run yet without running them. Used in the |
495 // destructor to make sure all the task's destructors get called. Returns | 466 // destructor to make sure all the task's destructors get called. Returns |
496 // true if some work was done. | 467 // true if some work was done. |
497 bool DeletePendingTasks(); | 468 bool DeletePendingTasks(); |
498 | 469 |
499 // Calcuates the time at which a PendingTask should run. | 470 // Calculates the time at which a PendingTask should run. |
500 base::TimeTicks CalculateDelayedRuntime(int64 delay_ms); | 471 base::TimeTicks CalculateDelayedRuntime(int64 delay_ms); |
501 | 472 |
502 // Start recording histogram info about events and action IF it was enabled | 473 // Start recording histogram info about events and action IF it was enabled |
503 // and IF the statistics recorder can accept a registration of our histogram. | 474 // and IF the statistics recorder can accept a registration of our histogram. |
504 void StartHistogrammer(); | 475 void StartHistogrammer(); |
505 | 476 |
506 // Add occurence of event to our histogram, so that we can see what is being | 477 // Add occurrence of event to our histogram, so that we can see what is being |
507 // done in a specific MessageLoop instance (i.e., specific thread). | 478 // done in a specific MessageLoop instance (i.e., specific thread). |
508 // If message_histogram_ is NULL, this is a no-op. | 479 // If message_histogram_ is NULL, this is a no-op. |
509 void HistogramEvent(int event); | 480 void HistogramEvent(int event); |
510 | 481 |
511 // base::MessagePump::Delegate methods: | 482 // base::MessagePump::Delegate methods: |
512 virtual bool DoWork(); | 483 virtual bool DoWork(); |
513 virtual bool DoDelayedWork(base::TimeTicks* next_delayed_work_time); | 484 virtual bool DoDelayedWork(base::TimeTicks* next_delayed_work_time); |
514 virtual bool DoIdleWork(); | 485 virtual bool DoIdleWork(); |
515 | 486 |
516 Type type_; | 487 Type type_; |
517 | 488 |
518 // A list of tasks that need to be processed by this instance. Note that | 489 // A list of tasks that need to be processed by this instance. Note that |
519 // this queue is only accessed (push/pop) by our current thread. | 490 // this queue is only accessed (push/pop) by our current thread. |
520 TaskQueue work_queue_; | 491 base::TaskQueue work_queue_; |
521 | 492 |
522 // Contains delayed tasks, sorted by their 'delayed_run_time' property. | 493 // Contains delayed tasks, sorted by their 'delayed_run_time' property. |
523 DelayedTaskQueue delayed_work_queue_; | 494 DelayedTaskQueue delayed_work_queue_; |
524 | 495 |
525 // A recent snapshot of Time::Now(), used to check delayed_work_queue_. | 496 // A recent snapshot of Time::Now(), used to check delayed_work_queue_. |
526 base::TimeTicks recent_time_; | 497 base::TimeTicks recent_time_; |
527 | 498 |
528 // A queue of non-nestable tasks that we had to defer because when it came | 499 // A queue of non-nestable tasks that we had to defer because when it came |
529 // time to execute them we were in a nested message loop. They will execute | 500 // time to execute them we were in a nested message loop. They will execute |
530 // once we're out of nested message loops. | 501 // once we're out of nested message loops. |
531 TaskQueue deferred_non_nestable_work_queue_; | 502 base::TaskQueue deferred_non_nestable_work_queue_; |
532 | 503 |
533 scoped_refptr<base::MessagePump> pump_; | 504 scoped_refptr<base::MessagePump> pump_; |
534 | 505 |
535 ObserverList<DestructionObserver> destruction_observers_; | 506 ObserverList<DestructionObserver> destruction_observers_; |
536 | 507 |
537 // A recursion block that prevents accidentally running additonal tasks when | 508 // A recursion block that prevents accidentally running additional tasks when |
538 // insider a (accidentally induced?) nested message pump. | 509 // insider a (accidentally induced?) nested message pump. |
539 bool nestable_tasks_allowed_; | 510 bool nestable_tasks_allowed_; |
540 | 511 |
541 bool exception_restoration_; | 512 bool exception_restoration_; |
542 | 513 |
543 std::string thread_name_; | 514 std::string thread_name_; |
544 // A profiling histogram showing the counts of various messages and events. | 515 // A profiling histogram showing the counts of various messages and events. |
545 base::Histogram* message_histogram_; | 516 base::Histogram* message_histogram_; |
546 | 517 |
547 // A null terminated list which creates an incoming_queue of tasks that are | 518 // A null terminated list which creates an incoming_queue of tasks that are |
548 // acquired under a mutex for processing on this instance's thread. These | 519 // acquired under a mutex for processing on this instance's thread. These |
549 // tasks have not yet been sorted out into items for our work_queue_ vs items | 520 // tasks have not yet been sorted out into items for our work_queue_ vs items |
550 // that will be handled by the TimerManager. | 521 // that will be handled by the TimerManager. |
551 TaskQueue incoming_queue_; | 522 base::TaskQueue incoming_queue_; |
552 // Protect access to incoming_queue_. | 523 // Protect access to incoming_queue_. |
553 mutable base::Lock incoming_queue_lock_; | 524 mutable base::Lock incoming_queue_lock_; |
554 | 525 |
555 RunState* state_; | 526 RunState* state_; |
556 | 527 |
557 // The need for this variable is subtle. Please see implementation comments | 528 // The need for this variable is subtle. Please see implementation comments |
558 // around where it is used. | 529 // around where it is used. |
559 bool should_leak_tasks_; | 530 bool should_leak_tasks_; |
560 | 531 |
561 #if defined(OS_WIN) | 532 #if defined(OS_WIN) |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 #endif // defined(OS_POSIX) | 669 #endif // defined(OS_POSIX) |
699 }; | 670 }; |
700 | 671 |
701 // Do not add any member variables to MessageLoopForIO! This is important b/c | 672 // Do not add any member variables to MessageLoopForIO! This is important b/c |
702 // MessageLoopForIO is often allocated via MessageLoop(TYPE_IO). Any extra | 673 // MessageLoopForIO is often allocated via MessageLoop(TYPE_IO). Any extra |
703 // data that you need should be stored on the MessageLoop's pump_ instance. | 674 // data that you need should be stored on the MessageLoop's pump_ instance. |
704 COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO), | 675 COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO), |
705 MessageLoopForIO_should_not_have_extra_member_variables); | 676 MessageLoopForIO_should_not_have_extra_member_variables); |
706 | 677 |
707 #endif // BASE_MESSAGE_LOOP_H_ | 678 #endif // BASE_MESSAGE_LOOP_H_ |
OLD | NEW |