OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_MESSAGE_LOOP_H_ | 5 #ifndef BASE_MESSAGE_LOOP_MESSAGE_LOOP_H_ |
6 #define BASE_MESSAGE_LOOP_MESSAGE_LOOP_H_ | 6 #define BASE_MESSAGE_LOOP_MESSAGE_LOOP_H_ |
7 | 7 |
8 #include <queue> | 8 #include <queue> |
9 #include <string> | 9 #include <string> |
10 | 10 |
11 #include "base/base_export.h" | 11 #include "base/base_export.h" |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/callback_forward.h" | 13 #include "base/callback_forward.h" |
14 #include "base/location.h" | 14 #include "base/location.h" |
15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
16 #include "base/memory/scoped_ptr.h" | |
17 #include "base/message_loop/incoming_task_queue.h" | |
18 #include "base/message_loop/message_loop_proxy.h" | 16 #include "base/message_loop/message_loop_proxy.h" |
19 #include "base/message_loop/message_loop_proxy_impl.h" | |
20 #include "base/message_loop/message_pump.h" | 17 #include "base/message_loop/message_pump.h" |
21 #include "base/observer_list.h" | 18 #include "base/observer_list.h" |
22 #include "base/pending_task.h" | 19 #include "base/pending_task.h" |
23 #include "base/sequenced_task_runner_helpers.h" | 20 #include "base/sequenced_task_runner_helpers.h" |
24 #include "base/synchronization/lock.h" | 21 #include "base/synchronization/lock.h" |
25 #include "base/time/time.h" | 22 #include "base/time/time.h" |
26 #include "base/tracking_info.h" | 23 #include "base/tracking_info.h" |
27 | 24 |
28 #if defined(OS_WIN) | 25 #if defined(OS_WIN) |
29 // We need this to declare base::MessagePumpWin::Dispatcher, which we should | 26 // We need this to declare base::MessagePumpWin::Dispatcher, which we should |
(...skipping 12 matching lines...) Expand all Loading... |
42 #else | 39 #else |
43 #include "base/message_loop/message_pump_gtk.h" | 40 #include "base/message_loop/message_pump_gtk.h" |
44 #endif | 41 #endif |
45 | 42 |
46 #endif | 43 #endif |
47 #endif | 44 #endif |
48 | 45 |
49 namespace base { | 46 namespace base { |
50 | 47 |
51 class HistogramBase; | 48 class HistogramBase; |
| 49 class MessageLoopLockTest; |
52 class RunLoop; | 50 class RunLoop; |
53 class ThreadTaskRunnerHandle; | 51 class ThreadTaskRunnerHandle; |
54 #if defined(OS_ANDROID) | 52 #if defined(OS_ANDROID) |
55 class MessagePumpForUI; | 53 class MessagePumpForUI; |
56 #endif | 54 #endif |
57 class WaitableEvent; | |
58 | 55 |
59 // A MessageLoop is used to process events for a particular thread. There is | 56 // A MessageLoop is used to process events for a particular thread. There is |
60 // at most one MessageLoop instance per thread. | 57 // at most one MessageLoop instance per thread. |
61 // | 58 // |
62 // Events include at a minimum Task instances submitted to PostTask and its | 59 // Events include at a minimum Task instances submitted to PostTask and its |
63 // variants. Depending on the type of message pump used by the MessageLoop | 60 // variants. Depending on the type of message pump used by the MessageLoop |
64 // other events such as UI messages may be processed. On Windows APC calls (as | 61 // other events such as UI messages may be processed. On Windows APC calls (as |
65 // time permits) and signals sent to a registered set of HANDLEs may also be | 62 // time permits) and signals sent to a registered set of HANDLEs may also be |
66 // processed. | 63 // processed. |
67 // | 64 // |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 | 276 |
280 // Optional call to connect the thread name with this loop. | 277 // Optional call to connect the thread name with this loop. |
281 void set_thread_name(const std::string& thread_name) { | 278 void set_thread_name(const std::string& thread_name) { |
282 DCHECK(thread_name_.empty()) << "Should not rename this thread!"; | 279 DCHECK(thread_name_.empty()) << "Should not rename this thread!"; |
283 thread_name_ = thread_name; | 280 thread_name_ = thread_name; |
284 } | 281 } |
285 const std::string& thread_name() const { return thread_name_; } | 282 const std::string& thread_name() const { return thread_name_; } |
286 | 283 |
287 // Gets the message loop proxy associated with this message loop. | 284 // Gets the message loop proxy associated with this message loop. |
288 scoped_refptr<MessageLoopProxy> message_loop_proxy() { | 285 scoped_refptr<MessageLoopProxy> message_loop_proxy() { |
289 return message_loop_proxy_; | 286 return message_loop_proxy_.get(); |
290 } | 287 } |
291 | 288 |
292 // Enables or disables the recursive task processing. This happens in the case | 289 // Enables or disables the recursive task processing. This happens in the case |
293 // of recursive message loops. Some unwanted message loop may occurs when | 290 // of recursive message loops. Some unwanted message loop may occurs when |
294 // using common controls or printer functions. By default, recursive task | 291 // using common controls or printer functions. By default, recursive task |
295 // processing is disabled. | 292 // processing is disabled. |
296 // | 293 // |
297 // Please utilize |ScopedNestableTaskAllower| instead of calling these methods | 294 // Please utilize |ScopedNestableTaskAllower| instead of calling these methods |
298 // directly. In general nestable message loops are to be avoided. They are | 295 // directly. In general nestable message loops are to be avoided. They are |
299 // dangerous and difficult to get right, so please use with extreme caution. | 296 // dangerous and difficult to get right, so please use with extreme caution. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 | 352 |
356 protected: | 353 protected: |
357 virtual ~TaskObserver(); | 354 virtual ~TaskObserver(); |
358 }; | 355 }; |
359 | 356 |
360 // These functions can only be called on the same thread that |this| is | 357 // These functions can only be called on the same thread that |this| is |
361 // running on. | 358 // running on. |
362 void AddTaskObserver(TaskObserver* task_observer); | 359 void AddTaskObserver(TaskObserver* task_observer); |
363 void RemoveTaskObserver(TaskObserver* task_observer); | 360 void RemoveTaskObserver(TaskObserver* task_observer); |
364 | 361 |
| 362 // Returns true if the message loop has high resolution timers enabled. |
| 363 // Provided for testing. |
| 364 bool high_resolution_timers_enabled() { |
| 365 #if defined(OS_WIN) |
| 366 return !high_resolution_timer_expiration_.is_null(); |
| 367 #else |
| 368 return true; |
| 369 #endif |
| 370 } |
| 371 |
365 // When we go into high resolution timer mode, we will stay in hi-res mode | 372 // When we go into high resolution timer mode, we will stay in hi-res mode |
366 // for at least 1s. | 373 // for at least 1s. |
367 static const int kHighResolutionTimerModeLeaseTimeMs = 1000; | 374 static const int kHighResolutionTimerModeLeaseTimeMs = 1000; |
368 | 375 |
| 376 // Asserts that the MessageLoop is "idle". |
| 377 void AssertIdle() const; |
| 378 |
369 #if defined(OS_WIN) | 379 #if defined(OS_WIN) |
370 void set_os_modal_loop(bool os_modal_loop) { | 380 void set_os_modal_loop(bool os_modal_loop) { |
371 os_modal_loop_ = os_modal_loop; | 381 os_modal_loop_ = os_modal_loop; |
372 } | 382 } |
373 | 383 |
374 bool os_modal_loop() const { | 384 bool os_modal_loop() const { |
375 return os_modal_loop_; | 385 return os_modal_loop_; |
376 } | 386 } |
377 #endif // OS_WIN | 387 #endif // OS_WIN |
378 | 388 |
379 // Can only be called from the thread that owns the MessageLoop. | 389 // Can only be called from the thread that owns the MessageLoop. |
380 bool is_running() const; | 390 bool is_running() const; |
381 | 391 |
382 // Returns true if the message loop has high resolution timers enabled. | |
383 // Provided for testing. | |
384 bool IsHighResolutionTimerEnabledForTesting(); | |
385 | |
386 // Returns true if the message loop is "idle". Provided for testing. | |
387 bool IsIdleForTesting(); | |
388 | |
389 // Takes the incoming queue lock, signals |caller_wait| and waits until | |
390 // |caller_signal| is signalled. | |
391 void LockWaitUnLockForTesting(WaitableEvent* caller_wait, | |
392 WaitableEvent* caller_signal); | |
393 | |
394 //---------------------------------------------------------------------------- | 392 //---------------------------------------------------------------------------- |
395 protected: | 393 protected: |
396 | 394 |
397 #if defined(OS_WIN) | 395 #if defined(OS_WIN) |
398 MessagePumpWin* pump_win() { | 396 MessagePumpWin* pump_win() { |
399 return static_cast<MessagePumpWin*>(pump_.get()); | 397 return static_cast<MessagePumpWin*>(pump_.get()); |
400 } | 398 } |
401 #elif defined(OS_POSIX) && !defined(OS_IOS) | 399 #elif defined(OS_POSIX) && !defined(OS_IOS) |
402 MessagePumpLibevent* pump_libevent() { | 400 MessagePumpLibevent* pump_libevent() { |
403 return static_cast<MessagePumpLibevent*>(pump_.get()); | 401 return static_cast<MessagePumpLibevent*>(pump_.get()); |
404 } | 402 } |
405 #endif | 403 #endif |
406 | 404 |
407 scoped_ptr<MessagePump> pump_; | 405 scoped_refptr<MessagePump> pump_; |
408 | 406 |
409 private: | 407 private: |
410 friend class internal::IncomingTaskQueue; | |
411 friend class RunLoop; | 408 friend class RunLoop; |
| 409 friend class MessageLoopLockTest; |
412 | 410 |
413 // A function to encapsulate all the exception handling capability in the | 411 // A function to encapsulate all the exception handling capability in the |
414 // stacks around the running of a main message loop. It will run the message | 412 // stacks around the running of a main message loop. It will run the message |
415 // loop in a SEH try block or not depending on the set_SEH_restoration() | 413 // loop in a SEH try block or not depending on the set_SEH_restoration() |
416 // flag invoking respectively RunInternalInSEHFrame() or RunInternal(). | 414 // flag invoking respectively RunInternalInSEHFrame() or RunInternal(). |
417 void RunHandler(); | 415 void RunHandler(); |
418 | 416 |
419 #if defined(OS_WIN) | 417 #if defined(OS_WIN) |
420 __declspec(noinline) void RunInternalInSEHFrame(); | 418 __declspec(noinline) void RunInternalInSEHFrame(); |
421 #endif | 419 #endif |
422 | 420 |
423 // A surrounding stack frame around the running of the message loop that | 421 // A surrounding stack frame around the running of the message loop that |
424 // supports all saving and restoring of state, as is needed for any/all (ugly) | 422 // supports all saving and restoring of state, as is needed for any/all (ugly) |
425 // recursive calls. | 423 // recursive calls. |
426 void RunInternal(); | 424 void RunInternal(); |
427 | 425 |
428 // Called to process any delayed non-nestable tasks. | 426 // Called to process any delayed non-nestable tasks. |
429 bool ProcessNextDelayedNonNestableTask(); | 427 bool ProcessNextDelayedNonNestableTask(); |
430 | 428 |
431 // Runs the specified PendingTask. | 429 // Runs the specified PendingTask. |
432 void RunTask(const PendingTask& pending_task); | 430 void RunTask(const PendingTask& pending_task); |
433 | 431 |
434 // Calls RunTask or queues the pending_task on the deferred task list if it | 432 // Calls RunTask or queues the pending_task on the deferred task list if it |
435 // cannot be run right now. Returns true if the task was run. | 433 // cannot be run right now. Returns true if the task was run. |
436 bool DeferOrRunPendingTask(const PendingTask& pending_task); | 434 bool DeferOrRunPendingTask(const PendingTask& pending_task); |
437 | 435 |
438 // Adds the pending task to delayed_work_queue_. | 436 // Adds the pending task to delayed_work_queue_. |
439 void AddToDelayedWorkQueue(const PendingTask& pending_task); | 437 void AddToDelayedWorkQueue(const PendingTask& pending_task); |
440 | 438 |
| 439 // This function attempts to add pending task to our incoming_queue_. |
| 440 // The append can only possibly fail when |use_try_lock| is true. |
| 441 // |
| 442 // When |use_try_lock| is true, then this call will avoid blocking if |
| 443 // the related lock is already held, and will in that case (when the |
| 444 // lock is contended) fail to perform the append, and will return false. |
| 445 // |
| 446 // If the call succeeds to append to the queue, then this call |
| 447 // will return true. |
| 448 // |
| 449 // In all cases, the caller retains ownership of |pending_task|, but this |
| 450 // function will reset the value of pending_task->task. This is needed to |
| 451 // ensure that the posting call stack does not retain pending_task->task |
| 452 // beyond this function call. |
| 453 bool AddToIncomingQueue(PendingTask* pending_task, bool use_try_lock); |
| 454 |
| 455 // Load tasks from the incoming_queue_ into work_queue_ if the latter is |
| 456 // empty. The former requires a lock to access, while the latter is directly |
| 457 // accessible on this thread. |
| 458 void ReloadWorkQueue(); |
| 459 |
441 // Delete tasks that haven't run yet without running them. Used in the | 460 // Delete tasks that haven't run yet without running them. Used in the |
442 // destructor to make sure all the task's destructors get called. Returns | 461 // destructor to make sure all the task's destructors get called. Returns |
443 // true if some work was done. | 462 // true if some work was done. |
444 bool DeletePendingTasks(); | 463 bool DeletePendingTasks(); |
445 | 464 |
446 // Creates a process-wide unique ID to represent this task in trace events. | 465 // Calculates the time at which a PendingTask should run. |
447 // This will be mangled with a Process ID hash to reduce the likelyhood of | 466 TimeTicks CalculateDelayedRuntime(TimeDelta delay); |
448 // colliding with MessageLoop pointers on other processes. | |
449 uint64 GetTaskTraceID(const PendingTask& task); | |
450 | |
451 // Loads tasks from the incoming queue to |work_queue_| if the latter is | |
452 // empty. | |
453 void ReloadWorkQueue(); | |
454 | |
455 // Wakes up the message pump. Can be called on any thread. The caller is | |
456 // responsible for synchronizing ScheduleWork() calls. | |
457 void ScheduleWork(bool was_empty); | |
458 | 467 |
459 // Start recording histogram info about events and action IF it was enabled | 468 // Start recording histogram info about events and action IF it was enabled |
460 // and IF the statistics recorder can accept a registration of our histogram. | 469 // and IF the statistics recorder can accept a registration of our histogram. |
461 void StartHistogrammer(); | 470 void StartHistogrammer(); |
462 | 471 |
463 // Add occurrence of event to our histogram, so that we can see what is being | 472 // Add occurrence of event to our histogram, so that we can see what is being |
464 // done in a specific MessageLoop instance (i.e., specific thread). | 473 // done in a specific MessageLoop instance (i.e., specific thread). |
465 // If message_histogram_ is NULL, this is a no-op. | 474 // If message_histogram_ is NULL, this is a no-op. |
466 void HistogramEvent(int event); | 475 void HistogramEvent(int event); |
467 | 476 |
(...skipping 14 matching lines...) Expand all Loading... |
482 // A recent snapshot of Time::Now(), used to check delayed_work_queue_. | 491 // A recent snapshot of Time::Now(), used to check delayed_work_queue_. |
483 TimeTicks recent_time_; | 492 TimeTicks recent_time_; |
484 | 493 |
485 // A queue of non-nestable tasks that we had to defer because when it came | 494 // A queue of non-nestable tasks that we had to defer because when it came |
486 // time to execute them we were in a nested message loop. They will execute | 495 // time to execute them we were in a nested message loop. They will execute |
487 // once we're out of nested message loops. | 496 // once we're out of nested message loops. |
488 TaskQueue deferred_non_nestable_work_queue_; | 497 TaskQueue deferred_non_nestable_work_queue_; |
489 | 498 |
490 ObserverList<DestructionObserver> destruction_observers_; | 499 ObserverList<DestructionObserver> destruction_observers_; |
491 | 500 |
492 bool exception_restoration_; | |
493 | |
494 // A recursion block that prevents accidentally running additional tasks when | 501 // A recursion block that prevents accidentally running additional tasks when |
495 // insider a (accidentally induced?) nested message pump. | 502 // insider a (accidentally induced?) nested message pump. |
496 bool nestable_tasks_allowed_; | 503 bool nestable_tasks_allowed_; |
497 | 504 |
| 505 bool exception_restoration_; |
| 506 |
| 507 std::string thread_name_; |
| 508 // A profiling histogram showing the counts of various messages and events. |
| 509 HistogramBase* message_histogram_; |
| 510 |
| 511 // An incoming queue of tasks that are acquired under a mutex for processing |
| 512 // on this instance's thread. These tasks have not yet been sorted out into |
| 513 // items for our work_queue_ vs delayed_work_queue_. |
| 514 TaskQueue incoming_queue_; |
| 515 // Protect access to incoming_queue_. |
| 516 mutable Lock incoming_queue_lock_; |
| 517 |
| 518 RunLoop* run_loop_; |
| 519 |
498 #if defined(OS_WIN) | 520 #if defined(OS_WIN) |
| 521 TimeTicks high_resolution_timer_expiration_; |
499 // Should be set to true before calling Windows APIs like TrackPopupMenu, etc | 522 // Should be set to true before calling Windows APIs like TrackPopupMenu, etc |
500 // which enter a modal message loop. | 523 // which enter a modal message loop. |
501 bool os_modal_loop_; | 524 bool os_modal_loop_; |
502 #endif | 525 #endif |
503 | 526 |
504 std::string thread_name_; | 527 // The next sequence number to use for delayed tasks. Updating this counter is |
505 // A profiling histogram showing the counts of various messages and events. | 528 // protected by incoming_queue_lock_. |
506 HistogramBase* message_histogram_; | 529 int next_sequence_num_; |
507 | |
508 RunLoop* run_loop_; | |
509 | 530 |
510 ObserverList<TaskObserver> task_observers_; | 531 ObserverList<TaskObserver> task_observers_; |
511 | 532 |
512 scoped_refptr<internal::IncomingTaskQueue> incoming_task_queue_; | 533 // The message loop proxy associated with this message loop, if one exists. |
513 | 534 scoped_refptr<MessageLoopProxy> message_loop_proxy_; |
514 // The message loop proxy associated with this message loop. | |
515 scoped_refptr<internal::MessageLoopProxyImpl> message_loop_proxy_; | |
516 scoped_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_; | 535 scoped_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_; |
517 | 536 |
518 template <class T, class R> friend class base::subtle::DeleteHelperInternal; | 537 template <class T, class R> friend class base::subtle::DeleteHelperInternal; |
519 template <class T, class R> friend class base::subtle::ReleaseHelperInternal; | 538 template <class T, class R> friend class base::subtle::ReleaseHelperInternal; |
520 | 539 |
521 void DeleteSoonInternal(const tracked_objects::Location& from_here, | 540 void DeleteSoonInternal(const tracked_objects::Location& from_here, |
522 void(*deleter)(const void*), | 541 void(*deleter)(const void*), |
523 const void* object); | 542 const void* object); |
524 void ReleaseSoonInternal(const tracked_objects::Location& from_here, | 543 void ReleaseSoonInternal(const tracked_objects::Location& from_here, |
525 void(*releaser)(const void*), | 544 void(*releaser)(const void*), |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 | 720 |
702 // Do not add any member variables to MessageLoopForIO! This is important b/c | 721 // Do not add any member variables to MessageLoopForIO! This is important b/c |
703 // MessageLoopForIO is often allocated via MessageLoop(TYPE_IO). Any extra | 722 // MessageLoopForIO is often allocated via MessageLoop(TYPE_IO). Any extra |
704 // data that you need should be stored on the MessageLoop's pump_ instance. | 723 // data that you need should be stored on the MessageLoop's pump_ instance. |
705 COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO), | 724 COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO), |
706 MessageLoopForIO_should_not_have_extra_member_variables); | 725 MessageLoopForIO_should_not_have_extra_member_variables); |
707 | 726 |
708 } // namespace base | 727 } // namespace base |
709 | 728 |
710 #endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_H_ | 729 #endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_H_ |
OLD | NEW |