Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1127)

Side by Side Diff: trunk/src/base/message_loop/message_loop.h

Issue 19737005: Revert 212948 "Made MessagePump a non-thread safe class." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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_
OLDNEW
« no previous file with comments | « trunk/src/base/message_loop/incoming_task_queue.cc ('k') | trunk/src/base/message_loop/message_loop.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698