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"
21 namespace trace_event
{
22 class ConvertableToTraceFormat
;
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
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
{
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
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.
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.
65 // Must be last entry.
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.
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.
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
91 // A queue in the HAS_WORK state has tasks in the work task queue which
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.
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
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();
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
> {
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
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
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_