[Media Router] Add integration tests and e2e tests for media router and presentation...
[chromium-blink-merge.git] / components / scheduler / child / task_queue_manager.h
blobb61e7a858e6bc31223a89cd192c503479334406c
1 // Copyright 2014 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.
5 #ifndef CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_MANAGER_H_
6 #define CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_MANAGER_H_
8 #include "base/atomic_sequence_num.h"
9 #include "base/debug/task_annotator.h"
10 #include "base/macros.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/pending_task.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/synchronization/lock.h"
16 #include "base/threading/thread_checker.h"
17 #include "components/scheduler/child/task_queue_selector.h"
18 #include "components/scheduler/scheduler_export.h"
20 namespace base {
21 namespace trace_event {
22 class ConvertableToTraceFormat;
23 class TracedValue;
25 class TickClock;
28 namespace scheduler {
29 namespace internal {
30 class LazyNow;
31 class TaskQueue;
33 class NestableSingleThreadTaskRunner;
34 class TaskQueueSelector;
36 // The task queue manager provides N task queues and a selector interface for
37 // choosing which task queue to service next. Each task queue consists of two
38 // sub queues:
40 // 1. Incoming task queue. Tasks that are posted get immediately appended here.
41 // When a task is appended into an empty incoming queue, the task manager
42 // work function (DoWork) is scheduled to run on the main task runner.
44 // 2. Work queue. If a work queue is empty when DoWork() is entered, tasks from
45 // the incoming task queue (if any) are moved here. The work queues are
46 // registered with the selector as input to the scheduling decision.
48 class SCHEDULER_EXPORT TaskQueueManager : public TaskQueueSelector::Observer {
49 public:
50 // Keep TaskQueue::PumpPolicyToString in sync with this enum.
51 enum class PumpPolicy {
52 // Tasks posted to an incoming queue with an AUTO pump policy will be
53 // automatically scheduled for execution or transferred to the work queue
54 // automatically.
55 AUTO,
56 // Tasks posted to an incoming queue with an AFTER_WAKEUP pump policy
57 // will be scheduled for execution or transferred to the work queue
58 // automatically but only after another queue has executed a task.
59 AFTER_WAKEUP,
60 // Tasks posted to an incoming queue with a MANUAL will not be
61 // automatically scheduled for execution or transferred to the work queue.
62 // Instead, the selector should call PumpQueue() when necessary to bring
63 // in new tasks for execution.
64 MANUAL,
65 // Must be last entry.
66 PUMP_POLICY_COUNT,
67 FIRST_PUMP_POLICY = AUTO,
70 // Keep TaskQueue::WakeupPolicyToString in sync with this enum.
71 enum class WakeupPolicy {
72 // Tasks run on a queue with CAN_WAKE_OTHER_QUEUES wakeup policy can
73 // cause queues with the AFTER_WAKEUP PumpPolicy to be woken up.
74 CAN_WAKE_OTHER_QUEUES,
75 // Tasks run on a queue with DONT_WAKE_OTHER_QUEUES won't cause queues
76 // with the AFTER_WAKEUP PumpPolicy to be woken up.
77 DONT_WAKE_OTHER_QUEUES,
78 // Must be last entry.
79 WAKEUP_POLICY_COUNT,
80 FIRST_WAKEUP_POLICY = CAN_WAKE_OTHER_QUEUES,
83 enum class QueueState {
84 // A queue in the EMPTY state is empty and has no tasks in either the
85 // work or incoming task queue.
86 EMPTY,
87 // A queue in the NEEDS_PUMPING state has no tasks in the work task queue,
88 // but has tasks in the incoming task queue which can be pumped to make them
89 // runnable.
90 NEEDS_PUMPING,
91 // A queue in the HAS_WORK state has tasks in the work task queue which
92 // are runnable.
93 HAS_WORK,
96 // Create a task queue manager with |task_queue_count| task queues.
97 // |main_task_runner| identifies the thread on which where the tasks are
98 // eventually run. |selector| is used to choose which task queue to service.
99 // It should outlive this class. Category strings must have application
100 // lifetime (statics or literals). They may not include " chars.
101 TaskQueueManager(
102 size_t task_queue_count,
103 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner,
104 TaskQueueSelector* selector,
105 const char* disabled_by_default_tracing_category,
106 const char* disabled_by_default_verbose_tracing_category);
107 ~TaskQueueManager() override;
109 // Returns the task runner which targets the queue selected by |queue_index|.
110 scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerForQueue(
111 size_t queue_index) const;
113 // Sets the pump policy for the |queue_index| to |pump_policy|. By
114 // default queues are created with AUTO_PUMP_POLICY.
115 void SetPumpPolicy(size_t queue_index, PumpPolicy pump_policy);
117 // Sets the wakeup policy for the |queue_index| to |wakeup_policy|. By
118 // default queues are created with CAN_WAKE_OTHER_QUEUES.
119 void SetWakeupPolicy(size_t queue_index, WakeupPolicy wakeup_policy);
121 // Reloads new tasks from the incoming queue for |queue_index| into the work
122 // queue, regardless of whether the work queue is empty or not. After this,
123 // this function ensures that the tasks in the work queue, if any, are
124 // scheduled for execution.
126 // This function only needs to be called if automatic pumping is disabled
127 // for |queue_index|. See |SetQueueAutoPumpPolicy|. By default automatic
128 // pumping is enabled for all queues.
129 void PumpQueue(size_t queue_index);
131 // Returns true if there no tasks in either the work or incoming task queue
132 // identified by |queue_index|. Note that this function involves taking a
133 // lock, so calling it has some overhead.
134 bool IsQueueEmpty(size_t queue_index) const;
136 // Returns the QueueState of the queue identified by |queue_index|. Note that
137 // this function involves taking a lock, so calling it has some overhead.
138 QueueState GetQueueState(size_t queue_index) const;
140 // Returns the time of the next pending delayed task in any queue. Ignores
141 // any delayed tasks whose delay has expired. Returns a null TimeTicks object
142 // if no tasks are pending. NOTE this is somewhat expensive since every queue
143 // will get locked.
144 base::TimeTicks NextPendingDelayedTaskRunTime();
146 // Set the name |queue_index| for tracing purposes. |name| must be a pointer
147 // to a static string.
148 void SetQueueName(size_t queue_index, const char* name);
150 // Set the number of tasks executed in a single invocation of the task queue
151 // manager. Increasing the batch size can reduce the overhead of yielding
152 // back to the main message loop -- at the cost of potentially delaying other
153 // tasks posted to the main loop. The batch size is 1 by default.
154 void SetWorkBatchSize(int work_batch_size);
156 // These functions can only be called on the same thread that the task queue
157 // manager executes its tasks on.
158 void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer);
159 void RemoveTaskObserver(base::MessageLoop::TaskObserver* task_observer);
161 void SetTimeSourceForTesting(scoped_ptr<base::TickClock> time_source);
163 // Returns a bitmap where a bit is set iff a task on the corresponding queue
164 // was run since the last call to GetAndClearTaskWasRunOnQueueBitmap.
165 uint64 GetAndClearTaskWasRunOnQueueBitmap();
167 private:
168 // TaskQueueSelector::Observer implementation:
169 void OnTaskQueueEnabled() override;
171 friend class internal::LazyNow;
172 friend class internal::TaskQueue;
173 friend class TaskQueueManagerTest;
175 class DeletionSentinel : public base::RefCounted<DeletionSentinel> {
176 private:
177 friend class base::RefCounted<DeletionSentinel>;
178 ~DeletionSentinel() {}
181 // Called by the task queue to register a new pending task and allocate a
182 // sequence number for it.
183 void DidQueueTask(base::PendingTask* pending_task);
185 // Post a task to call DoWork() on the main task runner. Only one pending
186 // DoWork is allowed from the main thread, to prevent an explosion of pending
187 // DoWorks.
188 void MaybePostDoWorkOnMainRunner();
190 // Use the selector to choose a pending task and run it.
191 void DoWork(bool posted_from_main_thread);
193 // Delayed Tasks with run_times <= Now() are enqueued onto the work queue.
194 // Reloads any empty work queues which have automatic pumping enabled and
195 // which are eligible to be auto pumped based on the |previous_task| which was
196 // run and |should_trigger_wakeup| . Call with an empty |previous_task| if no
197 // task was just run. Returns true if any work queue has tasks after doing
198 // this.
199 bool UpdateWorkQueues(bool should_trigger_wakeup,
200 const base::PendingTask* previous_task);
202 // Chooses the next work queue to service. Returns true if |out_queue_index|
203 // indicates the queue from which the next task should be run, false to
204 // avoid running any tasks.
205 bool SelectWorkQueueToService(size_t* out_queue_index);
207 // Runs a single nestable task from the work queue designated by
208 // |queue_index|. If |has_previous_task| is true, |previous_task| should
209 // contain the previous task in this work batch. Non-nestable task are
210 // reposted on the run loop. The queue must not be empty.
211 // Returns true if the TaskQueueManager got deleted, and false otherwise.
212 bool ProcessTaskFromWorkQueue(size_t queue_index,
213 bool has_previous_task,
214 base::PendingTask* previous_task);
216 bool RunsTasksOnCurrentThread() const;
217 bool PostDelayedTask(const tracked_objects::Location& from_here,
218 const base::Closure& task,
219 base::TimeDelta delay);
220 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
221 const base::Closure& task,
222 base::TimeDelta delay);
223 internal::TaskQueue* Queue(size_t queue_index) const;
225 base::TimeTicks Now() const;
227 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
228 AsValueWithSelectorResult(bool should_run, size_t selected_queue) const;
229 static const char* PumpPolicyToString(PumpPolicy pump_policy);
230 static const char* WakeupPolicyToString(WakeupPolicy wakeup_policy);
232 std::vector<scoped_refptr<internal::TaskQueue>> queues_;
233 base::AtomicSequenceNumber task_sequence_num_;
234 base::debug::TaskAnnotator task_annotator_;
236 base::ThreadChecker main_thread_checker_;
237 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner_;
238 TaskQueueSelector* selector_;
240 base::Closure do_work_from_main_thread_closure_;
241 base::Closure do_work_from_other_thread_closure_;
243 uint64 task_was_run_bitmap_;
245 // The pending_dowork_count_ is only tracked on the main thread since that's
246 // where re-entrant problems happen.
247 int pending_dowork_count_;
249 int work_batch_size_;
251 scoped_ptr<base::TickClock> time_source_;
253 base::ObserverList<base::MessageLoop::TaskObserver> task_observers_;
255 const char* disabled_by_default_tracing_category_;
257 scoped_refptr<DeletionSentinel> deletion_sentinel_;
258 base::WeakPtrFactory<TaskQueueManager> weak_factory_;
260 DISALLOW_COPY_AND_ASSIGN(TaskQueueManager);
263 } // namespace scheduler
265 #endif // CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_MANAGER_H_