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

Side by Side Diff: content/renderer/scheduler/task_queue_manager.cc

Issue 985813002: Experimental: Remove chromium shared timers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: More tests Created 5 years, 9 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 #include "content/renderer/scheduler/task_queue_manager.h" 5 #include "content/renderer/scheduler/task_queue_manager.h"
6 6
7 #include <queue> 7 #include <queue>
8 #include <set>
8 9
9 #include "base/bind.h" 10 #include "base/bind.h"
10 #include "base/trace_event/trace_event.h" 11 #include "base/trace_event/trace_event.h"
11 #include "base/trace_event/trace_event_argument.h" 12 #include "base/trace_event/trace_event_argument.h"
12 #include "cc/test/test_now_source.h" 13 #include "cc/test/test_now_source.h"
13 #include "content/renderer/scheduler/task_queue_selector.h" 14 #include "content/renderer/scheduler/task_queue_selector.h"
14 15
15 namespace { 16 namespace {
16 const int64_t kMaxTimeTicks = std::numeric_limits<int64>::max(); 17 const int64_t kMaxTimeTicks = std::numeric_limits<int64>::max();
17 } 18 }
(...skipping 17 matching lines...) Expand all
35 const base::Closure& task, 36 const base::Closure& task,
36 base::TimeDelta delay) override { 37 base::TimeDelta delay) override {
37 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); 38 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE);
38 } 39 }
39 40
40 bool IsQueueEmpty() const; 41 bool IsQueueEmpty() const;
41 42
42 void SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy); 43 void SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy);
43 void PumpQueue(); 44 void PumpQueue();
44 45
45 bool UpdateWorkQueue(base::TimeTicks* next_pending_delayed_task, 46 bool UpdateWorkQueue(base::TimeTicks now,
46 const base::PendingTask* previous_task); 47 const base::PendingTask* previous_task);
47 base::PendingTask TakeTaskFromWorkQueue(); 48 base::PendingTask TakeTaskFromWorkQueue();
48 49
49 void WillDeleteTaskQueueManager(); 50 void WillDeleteTaskQueueManager();
50 51
51 base::TaskQueue& work_queue() { return work_queue_; } 52 base::TaskQueue& work_queue() { return work_queue_; }
52 53
53 void set_name(const char* name) { name_ = name; } 54 void set_name(const char* name) { name_ = name; }
54 55
55 void AsValueInto(base::trace_event::TracedValue* state) const; 56 void AsValueInto(base::trace_event::TracedValue* state) const;
56 57
57 private: 58 private:
58 enum class TaskType { 59 enum class TaskType {
59 NORMAL, 60 NORMAL,
60 NON_NESTABLE, 61 NON_NESTABLE,
61 }; 62 };
62 63
63 ~TaskQueue() override; 64 ~TaskQueue() override;
64 65
65 bool PostDelayedTaskImpl(const tracked_objects::Location& from_here, 66 bool PostDelayedTaskImpl(const tracked_objects::Location& from_here,
66 const base::Closure& task, 67 const base::Closure& task,
67 base::TimeDelta delay, 68 base::TimeDelta delay,
68 TaskType task_type); 69 TaskType task_type);
69 70
70 // Adds a task at the end of the incoming task queue and schedules a call to 71 // Delayed task posted to the chromium run loop, which calls
71 // TaskQueueManager::DoWork() if the incoming queue was empty and automatic 72 // ScheduleDelayedWorkLocked to enqueue any delayed timers which should be run
72 // pumping is enabled. Can be called on an arbitrary thread. 73 // now.
73 void EnqueueTask(const base::PendingTask& pending_task); 74 void KickDelayedTasks();
75
76 // Enqueues any delayed timers which should be run now, and (maybe) posts
77 // KickDelayedTasks if there isn't already a timer posted on the chromium
78 // runloop for the next task's scheduled run time.
79 bool ScheduleDelayedWorkLocked(base::TimeTicks now);
80
81 // Enqueues any delayed timers which should be run now.
82 void EnqueueReadyDelayedTasksLocked(base::TimeTicks now);
74 83
75 void PumpQueueLocked(); 84 void PumpQueueLocked();
76 bool TaskIsOlderThanQueuedTasks(const base::PendingTask* task); 85 bool TaskIsOlderThanQueuedTasks(const base::PendingTask* task);
77 bool ShouldAutoPumpQueueLocked(const base::PendingTask* previous_task); 86 bool ShouldAutoPumpQueueLocked(const base::PendingTask* previous_task);
78 void EnqueueTaskLocked(const base::PendingTask& pending_task); 87 void EnqueueTaskLocked(const base::PendingTask& pending_task);
79 88
80 void TraceQueueSize(bool is_locked) const; 89 void TraceQueueSize(bool is_locked) const;
81 static const char* PumpPolicyToString( 90 static const char* PumpPolicyToString(
82 TaskQueueManager::PumpPolicy pump_policy); 91 TaskQueueManager::PumpPolicy pump_policy);
83 static void QueueAsValueInto(const base::TaskQueue& queue, 92 static void QueueAsValueInto(const base::TaskQueue& queue,
84 base::trace_event::TracedValue* state); 93 base::trace_event::TracedValue* state);
85 static void TaskAsValueInto(const base::PendingTask& task, 94 static void TaskAsValueInto(const base::PendingTask& task,
86 base::trace_event::TracedValue* state); 95 base::trace_event::TracedValue* state);
87 96
88 // This lock protects all members except the work queue. 97 // This lock protects all members except the work queue.
89 mutable base::Lock lock_; 98 mutable base::Lock lock_;
90 TaskQueueManager* task_queue_manager_; 99 TaskQueueManager* task_queue_manager_;
91 base::TaskQueue incoming_queue_; 100 base::TaskQueue incoming_queue_;
92 TaskQueueManager::PumpPolicy pump_policy_; 101 TaskQueueManager::PumpPolicy pump_policy_;
93 const char* name_; 102 const char* name_;
94 std::priority_queue<base::TimeTicks, 103 base::DelayedTaskQueue delayed_task_queue_;
95 std::vector<base::TimeTicks>, 104 std::set<base::TimeTicks> in_flight_kick_delayed_tasks_;
96 std::greater<base::TimeTicks>> delayed_task_run_times_;
97 105
98 base::TaskQueue work_queue_; 106 base::TaskQueue work_queue_;
99 107
100 DISALLOW_COPY_AND_ASSIGN(TaskQueue); 108 DISALLOW_COPY_AND_ASSIGN(TaskQueue);
101 }; 109 };
102 110
103 TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager) 111 TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager)
104 : task_queue_manager_(task_queue_manager), 112 : task_queue_manager_(task_queue_manager),
105 pump_policy_(TaskQueueManager::PumpPolicy::AUTO), 113 pump_policy_(TaskQueueManager::PumpPolicy::AUTO),
106 name_(nullptr) { 114 name_(nullptr) {
107 } 115 }
108 116
109 TaskQueue::~TaskQueue() { 117 TaskQueue::~TaskQueue() {
110 } 118 }
111 119
112 void TaskQueue::WillDeleteTaskQueueManager() { 120 void TaskQueue::WillDeleteTaskQueueManager() {
113 base::AutoLock lock(lock_); 121 base::AutoLock lock(lock_);
114 task_queue_manager_ = nullptr; 122 task_queue_manager_ = nullptr;
123
124 // Clear all delayed tasks because we need them to be deleted before the blink
125 // heap goes away.
126 while (!delayed_task_queue_.empty())
127 delayed_task_queue_.pop();
115 } 128 }
116 129
117 bool TaskQueue::RunsTasksOnCurrentThread() const { 130 bool TaskQueue::RunsTasksOnCurrentThread() const {
118 base::AutoLock lock(lock_); 131 base::AutoLock lock(lock_);
119 if (!task_queue_manager_) 132 if (!task_queue_manager_)
120 return false; 133 return false;
121 return task_queue_manager_->RunsTasksOnCurrentThread(); 134 return task_queue_manager_->RunsTasksOnCurrentThread();
122 } 135 }
123 136
124 bool TaskQueue::PostDelayedTaskImpl(const tracked_objects::Location& from_here, 137 bool TaskQueue::PostDelayedTaskImpl(const tracked_objects::Location& from_here,
125 const base::Closure& task, 138 const base::Closure& task,
126 base::TimeDelta delay, 139 base::TimeDelta delay,
127 TaskType task_type) { 140 TaskType task_type) {
128 base::AutoLock lock(lock_); 141 base::AutoLock lock(lock_);
129 if (!task_queue_manager_) 142 if (!task_queue_manager_)
130 return false; 143 return false;
131 144
132 base::PendingTask pending_task(from_here, task, base::TimeTicks(), 145 base::PendingTask pending_task(from_here, task, base::TimeTicks(),
133 task_type != TaskType::NON_NESTABLE); 146 task_type != TaskType::NON_NESTABLE);
134 task_queue_manager_->DidQueueTask(&pending_task); 147 task_queue_manager_->DidQueueTask(&pending_task);
135 148
136 if (delay > base::TimeDelta()) { 149 if (delay > base::TimeDelta()) {
137 pending_task.delayed_run_time = task_queue_manager_->Now() + delay; 150 base::TimeTicks now = task_queue_manager_->Now();
138 delayed_task_run_times_.push(pending_task.delayed_run_time); 151 pending_task.delayed_run_time = now + delay;
139 return task_queue_manager_->PostDelayedTask( 152 delayed_task_queue_.push(pending_task);
140 FROM_HERE, Bind(&TaskQueue::EnqueueTask, this, pending_task), delay); 153 // If we changed the topmost task, then it is time to reschedule.
154 if (delayed_task_queue_.top().task.Equals(pending_task.task))
155 return ScheduleDelayedWorkLocked(now);
156 return true;
141 } 157 }
142 EnqueueTaskLocked(pending_task); 158 EnqueueTaskLocked(pending_task);
143 return true; 159 return true;
144 } 160 }
145 161
162 void TaskQueue::EnqueueReadyDelayedTasksLocked(base::TimeTicks now) {
163 lock_.AssertAcquired();
164 // Enqueue all delayed tasks that should be running now.
165 while (!delayed_task_queue_.empty() &&
166 delayed_task_queue_.top().delayed_run_time <= now) {
167 in_flight_kick_delayed_tasks_.erase(
168 delayed_task_queue_.top().delayed_run_time);
169 EnqueueTaskLocked(delayed_task_queue_.top());
170 delayed_task_queue_.pop();
171 }
172 }
173
174 bool TaskQueue::ScheduleDelayedWorkLocked(base::TimeTicks now) {
175 lock_.AssertAcquired();
176 EnqueueReadyDelayedTasksLocked(now);
177
178 // Any remaining tasks are in the future, so queue a task to kick them.
179 if (!delayed_task_queue_.empty()) {
180 base::TimeTicks next_run_time = delayed_task_queue_.top().delayed_run_time;
181 // Make sure we don't have more than one KickDelayedTasks posted for a
182 // particular scheduled run time (note it's fine to have multiple ones in
183 // flight for distinct run times).
184 if (in_flight_kick_delayed_tasks_.find(next_run_time) ==
185 in_flight_kick_delayed_tasks_.end()) {
186 in_flight_kick_delayed_tasks_.insert(next_run_time);
187 base::TimeDelta delay = next_run_time - now;
188 return task_queue_manager_->PostDelayedTask(
189 FROM_HERE, Bind(&TaskQueue::KickDelayedTasks, this), delay);
190 }
191 }
192 return true;
193 }
194
195 void TaskQueue::KickDelayedTasks() {
196 base::AutoLock lock(lock_);
197 ScheduleDelayedWorkLocked(task_queue_manager_->Now());
198 }
199
146 bool TaskQueue::IsQueueEmpty() const { 200 bool TaskQueue::IsQueueEmpty() const {
147 if (!work_queue_.empty()) 201 if (!work_queue_.empty())
148 return false; 202 return false;
149 203
150 { 204 {
151 base::AutoLock lock(lock_); 205 base::AutoLock lock(lock_);
152 return incoming_queue_.empty(); 206 return incoming_queue_.empty();
153 } 207 }
154 } 208 }
155 209
(...skipping 25 matching lines...) Expand all
181 if (pump_policy_ == TaskQueueManager::PumpPolicy::MANUAL) 235 if (pump_policy_ == TaskQueueManager::PumpPolicy::MANUAL)
182 return false; 236 return false;
183 if (pump_policy_ == TaskQueueManager::PumpPolicy::AFTER_WAKEUP && 237 if (pump_policy_ == TaskQueueManager::PumpPolicy::AFTER_WAKEUP &&
184 TaskIsOlderThanQueuedTasks(previous_task)) 238 TaskIsOlderThanQueuedTasks(previous_task))
185 return false; 239 return false;
186 if (incoming_queue_.empty()) 240 if (incoming_queue_.empty())
187 return false; 241 return false;
188 return true; 242 return true;
189 } 243 }
190 244
191 bool TaskQueue::UpdateWorkQueue( 245 bool TaskQueue::UpdateWorkQueue(base::TimeTicks now,
192 base::TimeTicks* next_pending_delayed_task, 246 const base::PendingTask* previous_task) {
193 const base::PendingTask* previous_task) {
194 if (!work_queue_.empty()) 247 if (!work_queue_.empty())
195 return true; 248 return true;
196 249
197 { 250 {
198 base::AutoLock lock(lock_); 251 base::AutoLock lock(lock_);
199 if (!delayed_task_run_times_.empty()) { 252 EnqueueReadyDelayedTasksLocked(now);
200 *next_pending_delayed_task =
201 std::min(*next_pending_delayed_task, delayed_task_run_times_.top());
202 }
203 if (!ShouldAutoPumpQueueLocked(previous_task)) 253 if (!ShouldAutoPumpQueueLocked(previous_task))
204 return false; 254 return false;
205 work_queue_.Swap(&incoming_queue_); 255 work_queue_.Swap(&incoming_queue_);
206 TraceQueueSize(true); 256 TraceQueueSize(true);
207 return true; 257 return true;
208 } 258 }
209 } 259 }
210 260
211 base::PendingTask TaskQueue::TakeTaskFromWorkQueue() { 261 base::PendingTask TaskQueue::TakeTaskFromWorkQueue() {
212 base::PendingTask pending_task = work_queue_.front(); 262 base::PendingTask pending_task = work_queue_.front();
(...skipping 11 matching lines...) Expand all
224 if (!is_locked) 274 if (!is_locked)
225 lock_.Acquire(); 275 lock_.Acquire();
226 else 276 else
227 lock_.AssertAcquired(); 277 lock_.AssertAcquired();
228 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), name_, 278 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), name_,
229 incoming_queue_.size() + work_queue_.size()); 279 incoming_queue_.size() + work_queue_.size());
230 if (!is_locked) 280 if (!is_locked)
231 lock_.Release(); 281 lock_.Release();
232 } 282 }
233 283
234 void TaskQueue::EnqueueTask(const base::PendingTask& pending_task) {
235 base::AutoLock lock(lock_);
236 EnqueueTaskLocked(pending_task);
237 }
238
239 void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) { 284 void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) {
240 lock_.AssertAcquired(); 285 lock_.AssertAcquired();
241 if (!task_queue_manager_) 286 if (!task_queue_manager_)
242 return; 287 return;
243 if (pump_policy_ == TaskQueueManager::PumpPolicy::AUTO && 288 if (pump_policy_ == TaskQueueManager::PumpPolicy::AUTO &&
244 incoming_queue_.empty()) 289 incoming_queue_.empty())
245 task_queue_manager_->MaybePostDoWorkOnMainRunner(); 290 task_queue_manager_->MaybePostDoWorkOnMainRunner();
246 incoming_queue_.push(pending_task); 291 incoming_queue_.push(pending_task);
247 292
248 if (!pending_task.delayed_run_time.is_null()) { 293 if (!pending_task.delayed_run_time.is_null()) {
249 // Update the time of the next pending delayed task.
250 while (!delayed_task_run_times_.empty() &&
251 delayed_task_run_times_.top() <= pending_task.delayed_run_time) {
252 delayed_task_run_times_.pop();
253 }
254 // Clear the delayed run time because we've already applied the delay 294 // Clear the delayed run time because we've already applied the delay
255 // before getting here. 295 // before getting here.
256 incoming_queue_.back().delayed_run_time = base::TimeTicks(); 296 incoming_queue_.back().delayed_run_time = base::TimeTicks();
257 } 297 }
258 TraceQueueSize(true); 298 TraceQueueSize(true);
259 } 299 }
260 300
261 void TaskQueue::SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy) { 301 void TaskQueue::SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy) {
262 base::AutoLock lock(lock_); 302 base::AutoLock lock(lock_);
263 if (pump_policy == TaskQueueManager::PumpPolicy::AUTO && 303 if (pump_policy == TaskQueueManager::PumpPolicy::AUTO &&
264 pump_policy_ != TaskQueueManager::PumpPolicy::AUTO) { 304 pump_policy_ != TaskQueueManager::PumpPolicy::AUTO) {
265 PumpQueueLocked(); 305 PumpQueueLocked();
266 } 306 }
267 pump_policy_ = pump_policy; 307 pump_policy_ = pump_policy;
268 } 308 }
269 309
270 void TaskQueue::PumpQueueLocked() { 310 void TaskQueue::PumpQueueLocked() {
271 lock_.AssertAcquired(); 311 lock_.AssertAcquired();
312 if (task_queue_manager_)
313 EnqueueReadyDelayedTasksLocked(task_queue_manager_->Now());
272 while (!incoming_queue_.empty()) { 314 while (!incoming_queue_.empty()) {
273 work_queue_.push(incoming_queue_.front()); 315 work_queue_.push(incoming_queue_.front());
274 incoming_queue_.pop(); 316 incoming_queue_.pop();
275 } 317 }
276 if (!work_queue_.empty()) 318 if (!work_queue_.empty())
277 task_queue_manager_->MaybePostDoWorkOnMainRunner(); 319 task_queue_manager_->MaybePostDoWorkOnMainRunner();
278 } 320 }
279 321
280 void TaskQueue::PumpQueue() { 322 void TaskQueue::PumpQueue() {
281 base::AutoLock lock(lock_); 323 base::AutoLock lock(lock_);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 for (size_t i = 0; i < task_queue_count; i++) { 400 for (size_t i = 0; i < task_queue_count; i++) {
359 scoped_refptr<internal::TaskQueue> queue( 401 scoped_refptr<internal::TaskQueue> queue(
360 make_scoped_refptr(new internal::TaskQueue(this))); 402 make_scoped_refptr(new internal::TaskQueue(this)));
361 queues_.push_back(queue); 403 queues_.push_back(queue);
362 } 404 }
363 405
364 std::vector<const base::TaskQueue*> work_queues; 406 std::vector<const base::TaskQueue*> work_queues;
365 for (const auto& queue: queues_) 407 for (const auto& queue: queues_)
366 work_queues.push_back(&queue->work_queue()); 408 work_queues.push_back(&queue->work_queue());
367 selector_->RegisterWorkQueues(work_queues); 409 selector_->RegisterWorkQueues(work_queues);
410 selector_->RegisterTaskQueueObserver(this);
368 } 411 }
369 412
370 TaskQueueManager::~TaskQueueManager() { 413 TaskQueueManager::~TaskQueueManager() {
371 TRACE_EVENT_OBJECT_DELETED_WITH_ID( 414 TRACE_EVENT_OBJECT_DELETED_WITH_ID(
372 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", 415 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager",
373 this); 416 this);
374 for (auto& queue : queues_) 417 for (auto& queue : queues_)
375 queue->WillDeleteTaskQueueManager(); 418 queue->WillDeleteTaskQueueManager();
376 } 419 }
377 420
(...skipping 19 matching lines...) Expand all
397 queue->SetPumpPolicy(pump_policy); 440 queue->SetPumpPolicy(pump_policy);
398 } 441 }
399 442
400 void TaskQueueManager::PumpQueue(size_t queue_index) { 443 void TaskQueueManager::PumpQueue(size_t queue_index) {
401 DCHECK(main_thread_checker_.CalledOnValidThread()); 444 DCHECK(main_thread_checker_.CalledOnValidThread());
402 internal::TaskQueue* queue = Queue(queue_index); 445 internal::TaskQueue* queue = Queue(queue_index);
403 queue->PumpQueue(); 446 queue->PumpQueue();
404 } 447 }
405 448
406 bool TaskQueueManager::UpdateWorkQueues( 449 bool TaskQueueManager::UpdateWorkQueues(
407 base::TimeTicks* next_pending_delayed_task, 450 base::TimeTicks now,
408 const base::PendingTask* previous_task) { 451 const base::PendingTask* previous_task) {
409 // TODO(skyostil): This is not efficient when the number of queues grows very 452 // TODO(skyostil): This is not efficient when the number of queues grows very
410 // large due to the number of locks taken. Consider optimizing when we get 453 // large due to the number of locks taken. Consider optimizing when we get
411 // there. 454 // there.
412 DCHECK(main_thread_checker_.CalledOnValidThread()); 455 DCHECK(main_thread_checker_.CalledOnValidThread());
413 bool has_work = false; 456 bool has_work = false;
414 for (auto& queue : queues_) { 457 for (auto& queue : queues_) {
415 has_work |= queue->UpdateWorkQueue(next_pending_delayed_task, 458 has_work |= queue->UpdateWorkQueue(now, previous_task);
416 previous_task);
417 if (!queue->work_queue().empty()) { 459 if (!queue->work_queue().empty()) {
418 // Currently we should not be getting tasks with delayed run times in any 460 // Currently we should not be getting tasks with delayed run times in any
419 // of the work queues. 461 // of the work queues.
420 DCHECK(queue->work_queue().front().delayed_run_time.is_null()); 462 DCHECK(queue->work_queue().front().delayed_run_time.is_null());
421 } 463 }
422 } 464 }
423 return has_work; 465 return has_work;
424 } 466 }
425 467
426 void TaskQueueManager::MaybePostDoWorkOnMainRunner() { 468 void TaskQueueManager::MaybePostDoWorkOnMainRunner() {
(...skipping 12 matching lines...) Expand all
439 on_main_thread)); 481 on_main_thread));
440 } 482 }
441 483
442 void TaskQueueManager::DoWork(bool posted_from_main_thread) { 484 void TaskQueueManager::DoWork(bool posted_from_main_thread) {
443 if (posted_from_main_thread) { 485 if (posted_from_main_thread) {
444 pending_dowork_count_--; 486 pending_dowork_count_--;
445 DCHECK_GE(pending_dowork_count_, 0); 487 DCHECK_GE(pending_dowork_count_, 0);
446 } 488 }
447 DCHECK(main_thread_checker_.CalledOnValidThread()); 489 DCHECK(main_thread_checker_.CalledOnValidThread());
448 490
449 base::TimeTicks next_pending_delayed_task( 491 // Pass nullptr to UpdateWorkQueues here to prevent waking up a
450 base::TimeTicks::FromInternalValue(kMaxTimeTicks));
451
452 // Pass nullptr to UpdateWorkQueues here to prevent waking up an
453 // pump-after-wakeup queue. 492 // pump-after-wakeup queue.
454 if (!UpdateWorkQueues(&next_pending_delayed_task, nullptr)) 493 if (!UpdateWorkQueues(Now(), nullptr))
455 return; 494 return;
456 495
457 base::PendingTask previous_task((tracked_objects::Location()), 496 base::PendingTask previous_task((tracked_objects::Location()),
458 (base::Closure())); 497 (base::Closure()));
459 for (int i = 0; i < work_batch_size_; i++) { 498 for (int i = 0; i < work_batch_size_; i++) {
460 // Interrupt the work batch if we should run the next delayed task.
461 if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks &&
462 Now() >= next_pending_delayed_task)
463 return;
464
465 size_t queue_index; 499 size_t queue_index;
466 if (!SelectWorkQueueToService(&queue_index)) 500 if (!SelectWorkQueueToService(&queue_index))
467 return; 501 return;
468 // Note that this function won't post another call to DoWork if one is 502 // Note that this function won't post another call to DoWork if one is
469 // already pending, so it is safe to call it in a loop. 503 // already pending, so it is safe to call it in a loop.
470 MaybePostDoWorkOnMainRunner(); 504 MaybePostDoWorkOnMainRunner();
471 ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task); 505 ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task);
472 506
473 if (!UpdateWorkQueues(&next_pending_delayed_task, &previous_task)) 507 if (!UpdateWorkQueues(Now(), &previous_task))
474 return; 508 return;
475 } 509 }
476 } 510 }
477 511
478 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { 512 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) {
479 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); 513 bool should_run = selector_->SelectWorkQueueToService(out_queue_index);
480 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( 514 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
481 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", this, 515 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", this,
482 AsValueWithSelectorResult(should_run, *out_queue_index)); 516 AsValueWithSelectorResult(should_run, *out_queue_index));
483 return should_run; 517 return should_run;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 queue->AsValueInto(state.get()); 610 queue->AsValueInto(state.get());
577 state->EndArray(); 611 state->EndArray();
578 state->BeginDictionary("selector"); 612 state->BeginDictionary("selector");
579 selector_->AsValueInto(state.get()); 613 selector_->AsValueInto(state.get());
580 state->EndDictionary(); 614 state->EndDictionary();
581 if (should_run) 615 if (should_run)
582 state->SetInteger("selected_queue", selected_queue); 616 state->SetInteger("selected_queue", selected_queue);
583 return state; 617 return state;
584 } 618 }
585 619
620 void TaskQueueManager::OnTaskQueueEnabled() {
621 MaybePostDoWorkOnMainRunner();
622 }
623
586 } // namespace content 624 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/scheduler/task_queue_manager.h ('k') | content/renderer/scheduler/task_queue_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698