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

Side by Side Diff: base/task/task_queue_manager.cc

Issue 637303003: content: Add task queue manager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Review comments. Created 6 years, 2 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
« no previous file with comments | « base/task/task_queue_manager.h ('k') | base/task/task_queue_manager_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "base/task/task_queue_manager.h"
6
7 #include "base/bind.h"
8 #include "base/debug/trace_event.h"
9 #include "base/task/task_queue_selector.h"
10
11 namespace base {
12
13 TaskQueueManager::TaskRunner::TaskRunner(TaskQueueManager* task_queue_manager,
14 size_t queue_index)
15 : task_queue_manager_(task_queue_manager), queue_index_(queue_index) {
16 }
17
18 TaskQueueManager::TaskRunner::~TaskRunner() {
19 }
20
21 bool TaskQueueManager::TaskRunner::RunsTasksOnCurrentThread() const {
22 return task_queue_manager_->RunsTasksOnCurrentThread();
23 }
24
25 bool TaskQueueManager::TaskRunner::PostDelayedTask(
26 const tracked_objects::Location& from_here,
27 const Closure& task,
28 TimeDelta delay) {
29 return task_queue_manager_->PostDelayedTask(
30 queue_index_, from_here, task, delay);
31 }
32
33 bool TaskQueueManager::TaskRunner::PostNonNestableDelayedTask(
34 const tracked_objects::Location& from_here,
35 const Closure& task,
36 TimeDelta delay) {
37 return task_queue_manager_->PostNonNestableDelayedTask(
38 queue_index_, from_here, task, delay);
39 }
40
41 TaskQueueManager::InternalTaskQueue::InternalTaskQueue() : auto_pump(true) {
42 }
43
44 TaskQueueManager::InternalTaskQueue::~InternalTaskQueue() {
45 }
46
47 TaskQueueManager::TaskQueueManager(
48 size_t task_queue_count,
49 scoped_refptr<SingleThreadTaskRunner> main_task_runner,
50 TaskQueueSelector* selector)
51 : main_task_runner_(main_task_runner),
52 selector_(selector),
53 weak_factory_(this) {
54 DCHECK(main_task_runner->RunsTasksOnCurrentThread());
55
56 for (size_t i = 0; i < task_queue_count; i++) {
57 scoped_ptr<InternalTaskQueue> queue(new InternalTaskQueue());
58 queue->task_runner = make_scoped_refptr(new TaskRunner(this, i));
59 queues_.push_back(queue.release());
60 }
61
62 std::vector<const TaskQueue*> work_queues;
63 for (size_t i = 0; i < queues_.size(); i++)
64 work_queues.push_back(&queues_[i]->work_queue);
65 selector_->RegisterWorkQueues(work_queues);
66 }
67
68 TaskQueueManager::~TaskQueueManager() {
69 }
70
71 TaskQueueManager::InternalTaskQueue* TaskQueueManager::Queue(
72 size_t queue_index) const {
73 DCHECK_LT(queue_index, queues_.size());
74 return queues_[queue_index];
75 }
76
77 scoped_refptr<SingleThreadTaskRunner> TaskQueueManager::TaskRunnerForQueue(
78 size_t queue_index) {
79 return Queue(queue_index)->task_runner;
80 }
81
82 bool TaskQueueManager::PollQueue(size_t queue_index) {
83 InternalTaskQueue* queue = Queue(queue_index);
84 if (!queue->work_queue.empty())
85 return true;
86 AutoLock lock(queue->incoming_queue_lock);
87 return !queue->incoming_queue.empty();
88 }
89
90 bool TaskQueueManager::ReloadWorkQueue(size_t queue_index) {
91 main_thread_checker_.CalledOnValidThread();
92 InternalTaskQueue* queue = Queue(queue_index);
93 DCHECK(queue->work_queue.empty());
94 AutoLock lock(queue->incoming_queue_lock);
95 if (!queue->auto_pump)
96 return false;
97 queue->work_queue.Swap(&queue->incoming_queue);
98 return !queue->work_queue.empty();
99 }
100
101 void TaskQueueManager::EnqueueTask(size_t queue_index,
102 const PendingTask& pending_task) {
103 InternalTaskQueue* queue = Queue(queue_index);
104 AutoLock lock(queue->incoming_queue_lock);
105 if (queue->auto_pump && queue->incoming_queue.empty())
106 ScheduleWork();
107 queue->incoming_queue.push(pending_task);
108 }
109
110 void TaskQueueManager::SetAutoPump(size_t queue_index, bool auto_pump) {
111 InternalTaskQueue* queue = Queue(queue_index);
112 AutoLock lock(queue->incoming_queue_lock);
113 if (auto_pump) {
114 queue->auto_pump = true;
115 PumpQueueLocked(queue);
116 } else {
117 queue->auto_pump = false;
118 }
119 }
120
121 void TaskQueueManager::PumpQueueLocked(InternalTaskQueue* queue) {
122 queue->incoming_queue_lock.AssertAcquired();
123 while (!queue->incoming_queue.empty()) {
124 queue->work_queue.push(queue->incoming_queue.front());
125 queue->incoming_queue.pop();
126 }
127 if (!queue->work_queue.empty())
128 ScheduleWork();
129 }
130
131 void TaskQueueManager::PumpQueue(size_t queue_index) {
132 InternalTaskQueue* queue = Queue(queue_index);
133 AutoLock lock(queue->incoming_queue_lock);
134 PumpQueueLocked(queue);
135 }
136
137 void TaskQueueManager::ScheduleWork() {
138 main_task_runner_->PostTask(
139 FROM_HERE, Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr()));
140 }
141
142 bool TaskQueueManager::ReloadWorkQueues() {
rmcilroy 2014/10/15 13:02:45 I was going to suggest renaming this function to R
Sami 2014/10/15 14:34:30 UpdateWorkQueues sgtm. I've now documented what th
143 bool has_work = false;
144 for (size_t i = 0; i < queues_.size(); i++) {
145 if (!queues_[i]->work_queue.empty())
146 has_work = true;
147 else if (ReloadWorkQueue(i))
148 has_work = true;
149 }
150 return has_work;
151 }
152
153 void TaskQueueManager::DoWork() {
154 main_thread_checker_.CalledOnValidThread();
155 if (!ReloadWorkQueues())
156 return;
157
158 size_t queue_index;
159 if (!selector_->SelectWorkQueueToService(&queue_index))
160 return;
161 ScheduleWork();
162 RunTaskFromWorkQueue(queue_index);
163 }
164
165 void TaskQueueManager::RunTaskFromWorkQueue(size_t queue_index) {
166 main_thread_checker_.CalledOnValidThread();
167 InternalTaskQueue* queue = Queue(queue_index);
168 DCHECK(!queue->work_queue.empty());
169 PendingTask pending_task = queue->work_queue.front();
170 queue->work_queue.pop();
171 task_annotator_.RunTask(
172 "TaskQueueManager::PostTask", "TaskQueueManager::RunTask", pending_task);
173 }
174
175 bool TaskQueueManager::RunsTasksOnCurrentThread() const {
176 return main_task_runner_->RunsTasksOnCurrentThread();
177 }
178
179 bool TaskQueueManager::PostDelayedTask(
180 size_t queue_index,
181 const tracked_objects::Location& from_here,
182 const Closure& task,
183 TimeDelta delay) {
184 int sequence_num = task_sequence_num_.GetNext();
185
186 PendingTask pending_task(from_here, task);
187 pending_task.sequence_num = sequence_num;
188
189 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", pending_task);
190 if (delay > TimeDelta()) {
191 return main_task_runner_->PostDelayedTask(
192 from_here,
193 Bind(&TaskQueueManager::EnqueueTask,
194 weak_factory_.GetWeakPtr(),
195 queue_index,
196 pending_task),
197 delay);
198 }
199 EnqueueTask(queue_index, pending_task);
200 return true;
201 }
202
203 bool TaskQueueManager::PostNonNestableDelayedTask(
204 size_t queue_index,
205 const tracked_objects::Location& from_here,
206 const Closure& task,
207 TimeDelta delay) {
208 // Defer non-nestable work to the main task runner.
209 return main_task_runner_->PostNonNestableDelayedTask(from_here, task, delay);
210 }
211
212 } // namespace content
OLDNEW
« no previous file with comments | « base/task/task_queue_manager.h ('k') | base/task/task_queue_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698