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 3 // found in the LICENSE file. 4 5 #ifndef BASE_MESSAGE_LOOP_INCOMING_TASK_QUEUE_H_ 6 #define BASE_MESSAGE_LOOP_INCOMING_TASK_QUEUE_H_ 7 8 #include "base/base_export.h" 9 #include "base/macros.h" 10 #include "base/memory/ref_counted.h" 11 #include "base/pending_task.h" 12 #include "base/synchronization/lock.h" 13 #include "base/time/time.h" 14 15 namespace base { 16 17 class MessageLoop; 18 class WaitableEvent; 19 20 namespace internal { 21 22 // Implements a queue of tasks posted to the message loop running on the current 23 // thread. This class takes care of synchronizing posting tasks from different 24 // threads and together with MessageLoop ensures clean shutdown. 25 class BASE_EXPORT IncomingTaskQueue 26 : public RefCountedThreadSafe<IncomingTaskQueue> { 27 public: 28 explicit IncomingTaskQueue(MessageLoop* message_loop); 29 30 // Appends a task to the incoming queue. Posting of all tasks is routed though 31 // AddToIncomingQueue() or TryAddToIncomingQueue() to make sure that posting 32 // task is properly synchronized between different threads. 33 // 34 // Returns true if the task was successfully added to the queue, otherwise 35 // returns false. In all cases, the ownership of |task| is transferred to the 36 // called method. 37 bool AddToIncomingQueue(const tracked_objects::Location& from_here, 38 const Closure& task, 39 TimeDelta delay, 40 bool nestable); 41 42 // Returns true if the queue contains tasks that require higher than default 43 // timer resolution. Currently only needed for Windows. 44 bool HasHighResolutionTasks(); 45 46 // Returns true if the message loop is "idle". Provided for testing. 47 bool IsIdleForTesting(); 48 49 // Loads tasks from the |incoming_queue_| into |*work_queue|. Must be called 50 // from the thread that is running the loop. Returns the number of tasks that 51 // require high resolution timers. 52 int ReloadWorkQueue(TaskQueue* work_queue); 53 54 // Disconnects |this| from the parent message loop. 55 void WillDestroyCurrentMessageLoop(); 56 57 // This should be called when the message loop becomes ready for 58 // scheduling work. 59 void StartScheduling(); 60 61 private: 62 friend class RefCountedThreadSafe<IncomingTaskQueue>; 63 virtual ~IncomingTaskQueue(); 64 65 // Calculates the time at which a PendingTask should run. 66 TimeTicks CalculateDelayedRuntime(TimeDelta delay); 67 68 // Adds a task to |incoming_queue_|. The caller retains ownership of 69 // |pending_task|, but this function will reset the value of 70 // |pending_task->task|. This is needed to ensure that the posting call stack 71 // does not retain |pending_task->task| beyond this function call. 72 bool PostPendingTask(PendingTask* pending_task); 73 74 // Wakes up the message loop and schedules work. 75 void ScheduleWork(); 76 77 // Number of tasks that require high resolution timing. This value is kept 78 // so that ReloadWorkQueue() completes in constant time. 79 int high_res_task_count_; 80 81 // The lock that protects access to the members of this class. 82 base::Lock incoming_queue_lock_; 83 84 // An incoming queue of tasks that are acquired under a mutex for processing 85 // on this instance's thread. These tasks have not yet been been pushed to 86 // |message_loop_|. 87 TaskQueue incoming_queue_; 88 89 // Points to the message loop that owns |this|. 90 MessageLoop* message_loop_; 91 92 // The next sequence number to use for delayed tasks. 93 int next_sequence_num_; 94 95 // True if our message loop has already been scheduled and does not need to be 96 // scheduled again until an empty reload occurs. 97 bool message_loop_scheduled_; 98 99 // True if we always need to call ScheduleWork when receiving a new task, even 100 // if the incoming queue was not empty. 101 const bool always_schedule_work_; 102 103 // False until StartScheduling() is called. 104 bool is_ready_for_scheduling_; 105 106 DISALLOW_COPY_AND_ASSIGN(IncomingTaskQueue); 107 }; 108 109 } // namespace internal 110 } // namespace base 111 112 #endif // BASE_MESSAGE_LOOP_INCOMING_TASK_QUEUE_H_ 113