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