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

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc

Issue 2326313003: Revert of Make canceling Timers fast. (Closed)
Patch Set: Created 4 years, 3 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "platform/scheduler/base/task_queue_impl.h" 5 #include "platform/scheduler/base/task_queue_impl.h"
6 6
7 #include "base/trace_event/blame_context.h" 7 #include "base/trace_event/blame_context.h"
8 #include "platform/scheduler/base/task_queue_manager.h" 8 #include "platform/scheduler/base/task_queue_manager.h"
9 #include "platform/scheduler/base/task_queue_manager_delegate.h" 9 #include "platform/scheduler/base/task_queue_manager_delegate.h"
10 #include "platform/scheduler/base/time_domain.h" 10 #include "platform/scheduler/base/time_domain.h"
11 #include "platform/scheduler/base/work_queue.h" 11 #include "platform/scheduler/base/work_queue.h"
12 12
13 namespace blink { 13 namespace blink {
14 namespace scheduler { 14 namespace scheduler {
15 15
16 TaskQueue::TaskHandle::TaskHandle() : enqueue_order_(0), sequence_number_(0) {}
17
18 TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue, uint64_t enqueue_order)
19 : enqueue_order_(enqueue_order),
20 #if DCHECK_IS_ON()
21 task_queue_(task_queue),
22 #endif
23 sequence_number_(0) {
24 DCHECK_GT(enqueue_order, 0ull);
25 }
26
27 TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue,
28 base::TimeTicks scheduled_run_time,
29 int sequence_number)
30 : enqueue_order_(0),
31 scheduled_run_time_(scheduled_run_time),
32 #if DCHECK_IS_ON()
33 task_queue_(task_queue),
34 #endif
35 sequence_number_(sequence_number) {
36 DCHECK(!scheduled_run_time.is_null());
37 }
38
39 TaskQueue::TaskHandle::operator bool() const {
40 return !scheduled_run_time_.is_null() ||
41 internal::EnqueueOrderGenerator::IsValidEnqueueOrder(enqueue_order_);
42 }
43
16 namespace internal { 44 namespace internal {
17 45
18 TaskQueueImpl::TaskQueueImpl( 46 TaskQueueImpl::TaskQueueImpl(
19 TaskQueueManager* task_queue_manager, 47 TaskQueueManager* task_queue_manager,
20 TimeDomain* time_domain, 48 TimeDomain* time_domain,
21 const Spec& spec, 49 const Spec& spec,
22 const char* disabled_by_default_tracing_category, 50 const char* disabled_by_default_tracing_category,
23 const char* disabled_by_default_verbose_tracing_category) 51 const char* disabled_by_default_verbose_tracing_category)
24 : thread_id_(base::PlatformThread::CurrentId()), 52 : thread_id_(base::PlatformThread::CurrentId()),
25 any_thread_(task_queue_manager, time_domain), 53 any_thread_(task_queue_manager, time_domain),
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 bool nestable, 109 bool nestable,
82 EnqueueOrder enqueue_order) 110 EnqueueOrder enqueue_order)
83 : PendingTask(posted_from, task, desired_run_time, nestable), 111 : PendingTask(posted_from, task, desired_run_time, nestable),
84 #ifndef NDEBUG 112 #ifndef NDEBUG
85 enqueue_order_set_(true), 113 enqueue_order_set_(true),
86 #endif 114 #endif
87 enqueue_order_(enqueue_order) { 115 enqueue_order_(enqueue_order) {
88 sequence_num = sequence_number; 116 sequence_num = sequence_number;
89 } 117 }
90 118
119 // static
120 TaskQueueImpl::Task TaskQueueImpl::Task::CreateFakeTaskFromHandle(
121 const TaskHandle& handle) {
122 if (handle.scheduled_run_time_.is_null()) {
123 // It's an immediate task.
124 return Task(tracked_objects::Location(), base::Closure(),
125 handle.scheduled_run_time_, handle.sequence_number_, false,
126 handle.enqueue_order_);
127 } else {
128 // It's a delayed task.
129 DCHECK_EQ(0ull, handle.enqueue_order_);
130 return Task(tracked_objects::Location(), base::Closure(),
131 handle.scheduled_run_time_, handle.sequence_number_, false);
132 }
133 }
134
135 bool TaskQueueImpl::Task::DelayedRunTimeComparator::operator()(
136 const Task& a,
137 const Task& b) const {
138 if (a.delayed_run_time < b.delayed_run_time)
139 return true;
140
141 if (a.delayed_run_time > b.delayed_run_time)
142 return false;
143
144 // If the times happen to match, then we use the sequence number to decide.
145 // Compare the difference to support integer roll-over.
146 return (a.sequence_num - b.sequence_num) < 0;
147 }
148
149 // static
150 bool TaskQueueImpl::Task::EnqueueOrderComparatorFn(const Task& a,
151 const Task& b) {
152 return a.enqueue_order() < b.enqueue_order();
153 }
154
155 // static
156 bool TaskQueueImpl::Task::DelayedRunTimeComparatorFn(const Task& a,
157 const Task& b) {
158 if (a.delayed_run_time < b.delayed_run_time)
159 return true;
160
161 if (a.delayed_run_time > b.delayed_run_time)
162 return false;
163
164 // If the times happen to match, then we use the sequence number to decide.
165 // Compare the difference to support integer roll-over.
166 return (a.sequence_num - b.sequence_num) < 0;
167 }
168
91 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, 169 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager,
92 TimeDomain* time_domain) 170 TimeDomain* time_domain)
93 : task_queue_manager(task_queue_manager), time_domain(time_domain) {} 171 : task_queue_manager(task_queue_manager),
172 time_domain(time_domain),
173 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) {
174 }
94 175
95 TaskQueueImpl::AnyThread::~AnyThread() {} 176 TaskQueueImpl::AnyThread::~AnyThread() {}
96 177
97 TaskQueueImpl::MainThreadOnly::MainThreadOnly( 178 TaskQueueImpl::MainThreadOnly::MainThreadOnly(
98 TaskQueueManager* task_queue_manager, 179 TaskQueueManager* task_queue_manager,
99 TaskQueueImpl* task_queue, 180 TaskQueueImpl* task_queue,
100 TimeDomain* time_domain) 181 TimeDomain* time_domain)
101 : task_queue_manager(task_queue_manager), 182 : task_queue_manager(task_queue_manager),
102 time_domain(time_domain), 183 time_domain(time_domain),
103 delayed_work_queue(new WorkQueue(task_queue, "delayed")), 184 delayed_work_queue(
104 immediate_work_queue(new WorkQueue(task_queue, "immediate")), 185 new WorkQueue(task_queue,
186 "delayed",
187 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)),
188 immediate_work_queue(
189 new WorkQueue(task_queue,
190 "immediate",
191 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)),
105 set_index(0), 192 set_index(0),
106 is_enabled(true), 193 is_enabled(true),
107 blame_context(nullptr), 194 blame_context(nullptr),
108 current_fence(0) {} 195 current_fence(0) {}
109 196
110 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} 197 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {}
111 198
112 void TaskQueueImpl::UnregisterTaskQueue() { 199 void TaskQueueImpl::UnregisterTaskQueue() {
113 base::AutoLock lock(any_thread_lock_); 200 base::AutoLock lock(any_thread_lock_);
114 if (main_thread_only().time_domain) 201 if (main_thread_only().time_domain)
115 main_thread_only().time_domain->UnregisterQueue(this); 202 main_thread_only().time_domain->UnregisterQueue(this);
116 if (!any_thread().task_queue_manager) 203 if (!any_thread().task_queue_manager)
117 return; 204 return;
118 any_thread().time_domain = nullptr; 205 any_thread().time_domain = nullptr;
119 main_thread_only().time_domain = nullptr; 206 main_thread_only().time_domain = nullptr;
120 any_thread().task_queue_manager->UnregisterTaskQueue(this); 207 any_thread().task_queue_manager->UnregisterTaskQueue(this);
121 208
122 any_thread().task_queue_manager = nullptr; 209 any_thread().task_queue_manager = nullptr;
123 main_thread_only().task_queue_manager = nullptr; 210 main_thread_only().task_queue_manager = nullptr;
124 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); 211 main_thread_only().delayed_incoming_queue.clear();
125 any_thread().immediate_incoming_queue = std::queue<Task>(); 212 any_thread().immediate_incoming_queue.clear();
126 main_thread_only().immediate_work_queue.reset(); 213 main_thread_only().immediate_work_queue.reset();
127 main_thread_only().delayed_work_queue.reset(); 214 main_thread_only().delayed_work_queue.reset();
128 } 215 }
129 216
130 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { 217 bool TaskQueueImpl::RunsTasksOnCurrentThread() const {
131 base::AutoLock lock(any_thread_lock_); 218 base::AutoLock lock(any_thread_lock_);
132 return base::PlatformThread::CurrentId() == thread_id_; 219 return base::PlatformThread::CurrentId() == thread_id_;
133 } 220 }
134 221
222 TaskQueue::TaskHandle TaskQueueImpl::PostCancellableDelayedTask(
223 const tracked_objects::Location& from_here,
224 const base::Closure& task,
225 base::TimeDelta delay) {
226 if (!main_thread_only().task_queue_manager)
227 return TaskHandle();
228
229 EnqueueOrder sequence_number =
230 main_thread_only().task_queue_manager->GetNextSequenceNumber();
231
232 if (delay.is_zero()) {
233 base::AutoLock lock(any_thread_lock_);
234 PushOntoImmediateIncomingQueueLocked(
235 Task(from_here, task, base::TimeTicks(), sequence_number, true,
236 sequence_number));
237
238 return TaskHandle(this, sequence_number);
239 } else {
240 DCHECK_GT(delay, base::TimeDelta());
241 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
242 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
243 PushOntoDelayedIncomingQueueFromMainThread(
244 Task(from_here, task, time_domain_delayed_run_time, sequence_number,
245 true),
246 time_domain_now);
247
248 return TaskHandle(this, time_domain_delayed_run_time, sequence_number);
249 }
250 }
251
252 bool TaskQueueImpl::CancelTask(const TaskQueue::TaskHandle& handle) {
253 if (!handle)
254 return false;
255
256 // If the TaskQueueManager has gone away, pretend we have canceled the task
257 // because this simplifies logic in TimerBase::stop.
258 if (!main_thread_only().task_queue_manager)
259 return true;
260
261 #if DCHECK_IS_ON()
262 DCHECK_EQ(handle.task_queue_, this);
263 #endif
264
265 Task fake_task = Task::CreateFakeTaskFromHandle(handle);
266 if (handle.scheduled_run_time_.is_null()) {
267 // It's an immediate task.
268 if (main_thread_only().immediate_work_queue->CancelTask(fake_task))
269 return true;
270
271 base::AutoLock lock(any_thread_lock_);
272 return any_thread().immediate_incoming_queue.erase(fake_task) > 0;
273 } else {
274 // It's a delayed task.
275 DelayedRunTimeQueue::iterator it =
276 main_thread_only().delayed_incoming_queue.find(fake_task);
277 if (it != main_thread_only().delayed_incoming_queue.end()) {
278 // It's safe to remove the wakeup from the TimeDomain only if this task's
279 // scheduled run time was unique within the queue.
280 bool can_cancel_timedomain_wakeup = true;
281 if (it != main_thread_only().delayed_incoming_queue.begin()) {
282 DelayedRunTimeQueue::iterator before = it;
283 before--;
284 if (before->delayed_run_time == handle.scheduled_run_time_)
285 can_cancel_timedomain_wakeup = false;
286 }
287 if (can_cancel_timedomain_wakeup) {
288 DelayedRunTimeQueue::iterator after = it;
289 after++;
290 if (after != main_thread_only().delayed_incoming_queue.end() &&
291 after->delayed_run_time == handle.scheduled_run_time_) {
292 can_cancel_timedomain_wakeup = false;
293 }
294 }
295 if (can_cancel_timedomain_wakeup) {
296 main_thread_only().time_domain->CancelDelayedWork(
297 this, handle.scheduled_run_time_);
298 }
299
300 main_thread_only().delayed_incoming_queue.erase(it);
301 return true;
302 }
303
304 return main_thread_only().delayed_work_queue->CancelTask(fake_task);
305 }
306 }
307
308 bool TaskQueueImpl::IsTaskPending(const TaskQueue::TaskHandle& handle) const {
309 if (!handle)
310 return false;
311
312 // If the TaskQueueManager has gone away the task got cancelled.
313 if (!main_thread_only().task_queue_manager)
314 return false;
315
316 #if DCHECK_IS_ON()
317 DCHECK_EQ(handle.task_queue_, this);
318 #endif
319
320 Task fake_task = Task::CreateFakeTaskFromHandle(handle);
321 if (handle.scheduled_run_time_.is_null()) {
322 // It's an immediate task.
323 if (main_thread_only().immediate_work_queue->IsTaskPending(fake_task))
324 return true;
325
326 base::AutoLock lock(any_thread_lock_);
327 return any_thread().immediate_incoming_queue.find(fake_task) !=
328 any_thread().immediate_incoming_queue.end();
329 } else {
330 // It's a delayed task.
331 DelayedRunTimeQueue::iterator it =
332 main_thread_only().delayed_incoming_queue.find(fake_task);
333 if (it != main_thread_only().delayed_incoming_queue.end())
334 return true;
335
336 return main_thread_only().delayed_work_queue->IsTaskPending(fake_task);
337 }
338 }
135 339
136 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, 340 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here,
137 const base::Closure& task, 341 const base::Closure& task,
138 base::TimeDelta delay) { 342 base::TimeDelta delay) {
139 if (delay.is_zero()) 343 if (delay.is_zero())
140 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); 344 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL);
141 345
142 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); 346 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL);
143 } 347 }
144 348
(...skipping 12 matching lines...) Expand all
157 const base::Closure& task, 361 const base::Closure& task,
158 TaskType task_type) { 362 TaskType task_type) {
159 base::AutoLock lock(any_thread_lock_); 363 base::AutoLock lock(any_thread_lock_);
160 if (!any_thread().task_queue_manager) 364 if (!any_thread().task_queue_manager)
161 return false; 365 return false;
162 366
163 EnqueueOrder sequence_number = 367 EnqueueOrder sequence_number =
164 any_thread().task_queue_manager->GetNextSequenceNumber(); 368 any_thread().task_queue_manager->GetNextSequenceNumber();
165 369
166 PushOntoImmediateIncomingQueueLocked( 370 PushOntoImmediateIncomingQueueLocked(
167 from_here, 371 Task(from_here, task, base::TimeTicks(), sequence_number,
168 task, 372 task_type != TaskType::NON_NESTABLE, sequence_number));
169 base::TimeTicks(),
170 sequence_number,
171 task_type != TaskType::NON_NESTABLE);
172 return true; 373 return true;
173 } 374 }
174 375
175 bool TaskQueueImpl::PostDelayedTaskImpl( 376 bool TaskQueueImpl::PostDelayedTaskImpl(
176 const tracked_objects::Location& from_here, 377 const tracked_objects::Location& from_here,
177 const base::Closure& task, 378 const base::Closure& task,
178 base::TimeDelta delay, 379 base::TimeDelta delay,
179 TaskType task_type) { 380 TaskType task_type) {
180 DCHECK_GT(delay, base::TimeDelta()); 381 DCHECK_GT(delay, base::TimeDelta());
181 if (base::PlatformThread::CurrentId() == thread_id_) { 382 if (base::PlatformThread::CurrentId() == thread_id_) {
(...skipping 25 matching lines...) Expand all
207 base::TimeTicks time_domain_now = any_thread().time_domain->Now(); 408 base::TimeTicks time_domain_now = any_thread().time_domain->Now();
208 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; 409 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
209 PushOntoDelayedIncomingQueueLocked( 410 PushOntoDelayedIncomingQueueLocked(
210 Task(from_here, task, time_domain_delayed_run_time, sequence_number, 411 Task(from_here, task, time_domain_delayed_run_time, sequence_number,
211 task_type != TaskType::NON_NESTABLE)); 412 task_type != TaskType::NON_NESTABLE));
212 } 413 }
213 return true; 414 return true;
214 } 415 }
215 416
216 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( 417 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread(
217 Task pending_task, base::TimeTicks now) { 418 Task pending_task,
419 base::TimeTicks now) {
218 main_thread_only().task_queue_manager->DidQueueTask(pending_task); 420 main_thread_only().task_queue_manager->DidQueueTask(pending_task);
219 421
220 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. 422 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue.
221 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 423 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
222 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); 424 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task));
223 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, 425 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time,
224 now); 426 now);
225 TraceQueueSize(false); 427 TraceQueueSize(false);
226 } 428 }
227 429
228 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { 430 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) {
229 any_thread().task_queue_manager->DidQueueTask(pending_task); 431 any_thread().task_queue_manager->DidQueueTask(pending_task);
230 432
231 int thread_hop_task_sequence_number = 433 int thread_hop_task_sequence_number =
232 any_thread().task_queue_manager->GetNextSequenceNumber(); 434 any_thread().task_queue_manager->GetNextSequenceNumber();
233 PushOntoImmediateIncomingQueueLocked( 435 PushOntoImmediateIncomingQueueLocked(
234 FROM_HERE, 436 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this,
235 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, 437 base::Passed(&pending_task)),
236 base::Passed(&pending_task)), 438 base::TimeTicks(), thread_hop_task_sequence_number, false,
237 base::TimeTicks(), 439 thread_hop_task_sequence_number));
238 thread_hop_task_sequence_number,
239 false);
240 } 440 }
241 441
242 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( 442 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) {
243 const tracked_objects::Location& posted_from,
244 const base::Closure& task,
245 base::TimeTicks desired_run_time,
246 EnqueueOrder sequence_number,
247 bool nestable) {
248 if (any_thread().immediate_incoming_queue.empty()) 443 if (any_thread().immediate_incoming_queue.empty())
249 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); 444 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
250 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make 445 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make
251 // it run. 446 // it run.
252 if (any_thread().immediate_incoming_queue.empty()) { 447 if (any_thread().immediate_incoming_queue.empty()) {
253 // There's no point posting a DoWork for a disabled queue, however we can 448 // There's no point posting a DoWork for a disabled queue, however we can
254 // only tell if it's disabled from the main thread. 449 // only tell if it's disabled from the main thread.
255 if (base::PlatformThread::CurrentId() == thread_id_) { 450 if (base::PlatformThread::CurrentId() == thread_id_) {
256 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) 451 if (main_thread_only().is_enabled && !BlockedByFenceLocked())
257 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 452 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
258 } else { 453 } else {
259 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
260 } 455 }
261 } 456 }
262 any_thread().immediate_incoming_queue.emplace( 457 any_thread().task_queue_manager->DidQueueTask(pending_task);
263 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber); 458 // We expect |pending_task| to be inserted at the end. Amoritized O(1).
264 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back()); 459 any_thread().immediate_incoming_queue.insert(
460 any_thread().immediate_incoming_queue.end(),
461 std::move(pending_task));
462 DCHECK_EQ(pending_task.enqueue_order(),
463 any_thread().immediate_incoming_queue.rbegin()->enqueue_order());
265 TraceQueueSize(true); 464 TraceQueueSize(true);
266 } 465 }
267 466
268 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { 467 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) {
269 DCHECK(main_thread_checker_.CalledOnValidThread()); 468 DCHECK(main_thread_checker_.CalledOnValidThread());
270 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 469 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
271 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); 470 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
272 // Make sure |delayed_run_time| isn't in the past. 471 // Make sure |delayed_run_time| isn't in the past.
273 if (delayed_run_time < time_domain_now) { 472 if (delayed_run_time < time_domain_now) {
274 delayed_run_time = time_domain_now; 473 delayed_run_time = time_domain_now;
275 pending_task.delayed_run_time = time_domain_now; 474 pending_task.delayed_run_time = time_domain_now;
276 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); 475 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task));
277 LazyNow lazy_now(time_domain_now); 476 LazyNow lazy_now(time_domain_now);
278 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now); 477 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now);
279 } else { 478 } else {
280 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); 479 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task));
281 main_thread_only().time_domain->ScheduleDelayedWork( 480 main_thread_only().time_domain->ScheduleDelayedWork(
282 this, delayed_run_time, main_thread_only().time_domain->Now()); 481 this, delayed_run_time, main_thread_only().time_domain->Now());
283 } 482 }
284 TraceQueueSize(false); 483 TraceQueueSize(false);
285 } 484 }
286 485
287 void TaskQueueImpl::SetQueueEnabled(bool enabled) { 486 void TaskQueueImpl::SetQueueEnabled(bool enabled) {
288 if (main_thread_only().is_enabled == enabled) 487 if (main_thread_only().is_enabled == enabled)
289 return; 488 return;
290 main_thread_only().is_enabled = enabled; 489 main_thread_only().is_enabled = enabled;
291 if (!main_thread_only().task_queue_manager) 490 if (!main_thread_only().task_queue_manager)
292 return; 491 return;
293 if (enabled) { 492 if (enabled) {
294 // Note it's the job of the selector to tell the TaskQueueManager if 493 // Note it's the job of the selector to tell the TaskQueueManager if
295 // a DoWork needs posting. 494 // a DoWork needs posting.
296 main_thread_only().task_queue_manager->selector_.EnableQueue(this); 495 main_thread_only().task_queue_manager->selector_.EnableQueue(this);
297 } else { 496 } else {
298 main_thread_only().task_queue_manager->selector_.DisableQueue(this); 497 main_thread_only().task_queue_manager->selector_.DisableQueue(this);
299 } 498 }
300 } 499 }
301 500
302 bool TaskQueueImpl::IsQueueEnabled() const { 501 bool TaskQueueImpl::IsQueueEnabled() const {
303 return main_thread_only().is_enabled; 502 return main_thread_only().is_enabled;
304 } 503 }
305 504
306 bool TaskQueueImpl::IsEmpty() const { 505 bool TaskQueueImpl::IsEmpty() const {
307 if (!main_thread_only().delayed_work_queue->Empty() || 506 if (!main_thread_only().delayed_work_queue->Empty() ||
308 !main_thread_only().delayed_incoming_queue.empty() ||
309 !main_thread_only().immediate_work_queue->Empty()) { 507 !main_thread_only().immediate_work_queue->Empty()) {
310 return false; 508 return false;
311 } 509 }
312 510
313 base::AutoLock lock(any_thread_lock_); 511 base::AutoLock lock(any_thread_lock_);
314 return any_thread().immediate_incoming_queue.empty(); 512 return any_thread().immediate_incoming_queue.empty() &&
513 main_thread_only().delayed_incoming_queue.empty();
315 } 514 }
316 515
317 bool TaskQueueImpl::HasPendingImmediateWork() const { 516 bool TaskQueueImpl::HasPendingImmediateWork() const {
318 // Any work queue tasks count as immediate work. 517 // Any work queue tasks count as immediate work.
319 if (!main_thread_only().delayed_work_queue->Empty() || 518 if (!main_thread_only().delayed_work_queue->Empty() ||
320 !main_thread_only().immediate_work_queue->Empty()) { 519 !main_thread_only().immediate_work_queue->Empty()) {
321 return true; 520 return true;
322 } 521 }
323 522
324 // Tasks on |delayed_incoming_queue| that could run now, count as 523 // Tasks on |delayed_incoming_queue| that could run now, count as
325 // immediate work. 524 // immediate work.
326 if (!main_thread_only().delayed_incoming_queue.empty() && 525 if (!main_thread_only().delayed_incoming_queue.empty() &&
327 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= 526 main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <=
328 main_thread_only().time_domain->CreateLazyNow().Now()) { 527 main_thread_only().time_domain->CreateLazyNow().Now()) {
329 return true; 528 return true;
330 } 529 }
331 530
332 // Finally tasks on |immediate_incoming_queue| count as immediate work. 531 // Finally tasks on |immediate_incoming_queue| count as immediate work.
333 base::AutoLock lock(any_thread_lock_); 532 base::AutoLock lock(any_thread_lock_);
334 return !any_thread().immediate_incoming_queue.empty(); 533 return !any_thread().immediate_incoming_queue.empty();
335 } 534 }
336 535
337 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { 536 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) {
338 // Enqueue all delayed tasks that should be running now, skipping any that 537 // Enqueue all delayed tasks that should be running now.
339 // have been canceled.
340 while (!main_thread_only().delayed_incoming_queue.empty()) { 538 while (!main_thread_only().delayed_incoming_queue.empty()) {
539 DelayedRunTimeQueue::iterator next_task =
540 main_thread_only().delayed_incoming_queue.begin();
541 if (next_task->delayed_run_time > lazy_now->Now())
542 break;
341 // TODO(alexclarke): Use extract() when C++17 is allowed. 543 // TODO(alexclarke): Use extract() when C++17 is allowed.
342 Task& task = 544 Task& task = const_cast<Task&>(*next_task);
343 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top());
344 if (task.task.IsCancelled()) {
345 main_thread_only().delayed_incoming_queue.pop();
346 continue;
347 }
348 if (task.delayed_run_time > lazy_now->Now())
349 break;
350 task.set_enqueue_order( 545 task.set_enqueue_order(
351 main_thread_only().task_queue_manager->GetNextSequenceNumber()); 546 main_thread_only().task_queue_manager->GetNextSequenceNumber());
352 main_thread_only().delayed_work_queue->Push(std::move(task)); 547 main_thread_only().delayed_work_queue->Push(std::move(task));
353 main_thread_only().delayed_incoming_queue.pop(); 548 main_thread_only().delayed_incoming_queue.erase(next_task);
354 } 549 }
355 } 550 }
356 551
357 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() { 552 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now) {
358 if (!main_thread_only().task_queue_manager) 553 if (!main_thread_only().task_queue_manager)
359 return false; 554 return;
555 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now);
556 TraceQueueSize(false);
557 }
360 558
361 if (!main_thread_only().immediate_work_queue->Empty()) 559 void TaskQueueImpl::UpdateImmediateWorkQueue() {
362 return true; 560 DCHECK(main_thread_only().immediate_work_queue->Empty());
561 base::AutoLock lock(any_thread_lock_);
562 if (!main_thread_only().task_queue_manager)
563 return;
363 564
364 base::AutoLock lock(any_thread_lock_);
365 main_thread_only().immediate_work_queue->SwapLocked( 565 main_thread_only().immediate_work_queue->SwapLocked(
366 any_thread().immediate_incoming_queue); 566 any_thread().immediate_incoming_queue);
367 // |immediate_work_queue| is now empty so updates are no longer required. 567
368 return false; 568 // |any_thread().immediate_incoming_queue| is now empty so
569 // TimeDomain::UpdateQueues no longer needs to consider this queue for
570 // reloading.
571 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this);
369 } 572 }
370 573
371 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { 574 void TaskQueueImpl::TraceQueueSize(bool is_locked) const {
372 bool is_tracing; 575 bool is_tracing;
373 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, 576 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_,
374 &is_tracing); 577 &is_tracing);
375 if (!is_tracing) 578 if (!is_tracing)
376 return; 579 return;
377 580
378 // It's only safe to access the work queues from the main thread. 581 // It's only safe to access the work queues from the main thread.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 state->SetInteger("immediate_incoming_queue_size", 643 state->SetInteger("immediate_incoming_queue_size",
441 any_thread().immediate_incoming_queue.size()); 644 any_thread().immediate_incoming_queue.size());
442 state->SetInteger("delayed_incoming_queue_size", 645 state->SetInteger("delayed_incoming_queue_size",
443 main_thread_only().delayed_incoming_queue.size()); 646 main_thread_only().delayed_incoming_queue.size());
444 state->SetInteger("immediate_work_queue_size", 647 state->SetInteger("immediate_work_queue_size",
445 main_thread_only().immediate_work_queue->Size()); 648 main_thread_only().immediate_work_queue->Size());
446 state->SetInteger("delayed_work_queue_size", 649 state->SetInteger("delayed_work_queue_size",
447 main_thread_only().delayed_work_queue->Size()); 650 main_thread_only().delayed_work_queue->Size());
448 if (!main_thread_only().delayed_incoming_queue.empty()) { 651 if (!main_thread_only().delayed_incoming_queue.empty()) {
449 base::TimeDelta delay_to_next_task = 652 base::TimeDelta delay_to_next_task =
450 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - 653 (main_thread_only().delayed_incoming_queue.begin()->delayed_run_time -
451 main_thread_only().time_domain->CreateLazyNow().Now()); 654 main_thread_only().time_domain->CreateLazyNow().Now());
452 state->SetDouble("delay_to_next_task_ms", 655 state->SetDouble("delay_to_next_task_ms",
453 delay_to_next_task.InMillisecondsF()); 656 delay_to_next_task.InMillisecondsF());
454 } 657 }
455 if (verbose_tracing_enabled) { 658 if (verbose_tracing_enabled) {
456 state->BeginArray("immediate_incoming_queue"); 659 state->BeginArray("immediate_incoming_queue");
457 QueueAsValueInto(any_thread().immediate_incoming_queue, state); 660 QueueAsValueInto(any_thread().immediate_incoming_queue, state);
458 state->EndArray(); 661 state->EndArray();
459 state->BeginArray("delayed_work_queue"); 662 state->BeginArray("delayed_work_queue");
460 main_thread_only().delayed_work_queue->AsValueInto(state); 663 main_thread_only().delayed_work_queue->AsValueInto(state);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 // Tasks posted after this point will have a strictly higher enqueue order 746 // Tasks posted after this point will have a strictly higher enqueue order
544 // and will be blocked from running. 747 // and will be blocked from running.
545 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( 748 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence(
546 main_thread_only().current_fence); 749 main_thread_only().current_fence);
547 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( 750 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence(
548 main_thread_only().current_fence); 751 main_thread_only().current_fence);
549 752
550 if (!task_unblocked && previous_fence) { 753 if (!task_unblocked && previous_fence) {
551 base::AutoLock lock(any_thread_lock_); 754 base::AutoLock lock(any_thread_lock_);
552 if (!any_thread().immediate_incoming_queue.empty() && 755 if (!any_thread().immediate_incoming_queue.empty() &&
553 any_thread().immediate_incoming_queue.front().enqueue_order() > 756 any_thread().immediate_incoming_queue.begin()->enqueue_order() >
554 previous_fence && 757 previous_fence &&
555 any_thread().immediate_incoming_queue.front().enqueue_order() < 758 any_thread().immediate_incoming_queue.begin()->enqueue_order() <
556 main_thread_only().current_fence) { 759 main_thread_only().current_fence) {
557 task_unblocked = true; 760 task_unblocked = true;
558 } 761 }
559 } 762 }
560 763
561 if (main_thread_only().is_enabled && task_unblocked) { 764 if (main_thread_only().is_enabled && task_unblocked) {
562 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 765 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
563 FROM_HERE); 766 FROM_HERE);
564 } 767 }
565 } 768 }
566 769
567 void TaskQueueImpl::RemoveFence() { 770 void TaskQueueImpl::RemoveFence() {
568 if (!main_thread_only().task_queue_manager) 771 if (!main_thread_only().task_queue_manager)
569 return; 772 return;
570 773
571 EnqueueOrder previous_fence = main_thread_only().current_fence; 774 EnqueueOrder previous_fence = main_thread_only().current_fence;
572 main_thread_only().current_fence = 0; 775 main_thread_only().current_fence = 0;
573 776
574 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); 777 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence();
575 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); 778 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence();
576 779
577 if (!task_unblocked && previous_fence) { 780 if (!task_unblocked && previous_fence) {
578 base::AutoLock lock(any_thread_lock_); 781 base::AutoLock lock(any_thread_lock_);
579 if (!any_thread().immediate_incoming_queue.empty() && 782 if (!any_thread().immediate_incoming_queue.empty() &&
580 any_thread().immediate_incoming_queue.front().enqueue_order() > 783 any_thread().immediate_incoming_queue.begin()->enqueue_order() >
581 previous_fence) { 784 previous_fence) {
582 task_unblocked = true; 785 task_unblocked = true;
583 } 786 }
584 } 787 }
585 788
586 if (main_thread_only().is_enabled && task_unblocked) { 789 if (main_thread_only().is_enabled && task_unblocked) {
587 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 790 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
588 FROM_HERE); 791 FROM_HERE);
589 } 792 }
590 } 793 }
591 794
592 bool TaskQueueImpl::BlockedByFence() const { 795 bool TaskQueueImpl::BlockedByFence() const {
593 if (!main_thread_only().current_fence) 796 if (!main_thread_only().current_fence)
594 return false; 797 return false;
595 798
596 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 799 if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
597 !main_thread_only().delayed_work_queue->BlockedByFence()) { 800 !main_thread_only().delayed_work_queue->BlockedByFence()) {
598 return false; 801 return false;
599 } 802 }
600 803
601 base::AutoLock lock(any_thread_lock_); 804 base::AutoLock lock(any_thread_lock_);
602 if (any_thread().immediate_incoming_queue.empty()) 805 if (any_thread().immediate_incoming_queue.empty())
603 return true; 806 return true;
604 807
605 return any_thread().immediate_incoming_queue.front().enqueue_order() > 808 return any_thread().immediate_incoming_queue.begin()->enqueue_order() >
606 main_thread_only().current_fence; 809 main_thread_only().current_fence;
607 } 810 }
608 811
609 bool TaskQueueImpl::BlockedByFenceLocked() const { 812 bool TaskQueueImpl::BlockedByFenceLocked() const {
610 if (!main_thread_only().current_fence) 813 if (!main_thread_only().current_fence)
611 return false; 814 return false;
612 815
613 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 816 if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
614 !main_thread_only().delayed_work_queue->BlockedByFence()) { 817 !main_thread_only().delayed_work_queue->BlockedByFence()) {
615 return false; 818 return false;
616 } 819 }
617 820
618 if (any_thread().immediate_incoming_queue.empty()) 821 if (any_thread().immediate_incoming_queue.empty())
619 return true; 822 return true;
620 823
621 return any_thread().immediate_incoming_queue.front().enqueue_order() > 824 return any_thread().immediate_incoming_queue.begin()->enqueue_order() >
622 main_thread_only().current_fence; 825 main_thread_only().current_fence;
623 } 826 }
624 827
625 // static 828 // static
626 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, 829 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue,
627 base::trace_event::TracedValue* state) { 830 base::trace_event::TracedValue* state) {
628 // Remove const to search |queue| in the destructive manner. Restore the 831 for (const Task& task : queue) {
629 // content from |visited| later. 832 TaskAsValueInto(task, state);
630 std::queue<Task>* mutable_queue = const_cast<std::queue<Task>*>(&queue);
631 std::queue<Task> visited;
632 while (!mutable_queue->empty()) {
633 TaskAsValueInto(mutable_queue->front(), state);
634 visited.push(std::move(mutable_queue->front()));
635 mutable_queue->pop();
636 } 833 }
637 *mutable_queue = std::move(visited);
638 } 834 }
639 835
640 // static 836 // static
641 void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue, 837 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue,
642 base::trace_event::TracedValue* state) { 838 base::trace_event::TracedValue* state) {
643 // Remove const to search |queue| in the destructive manner. Restore the 839 for (const Task& task : queue) {
644 // content from |visited| later. 840 TaskAsValueInto(task, state);
645 std::priority_queue<Task>* mutable_queue =
646 const_cast<std::priority_queue<Task>*>(&queue);
647 std::priority_queue<Task> visited;
648 while (!mutable_queue->empty()) {
649 TaskAsValueInto(mutable_queue->top(), state);
650 visited.push(std::move(const_cast<Task&>(mutable_queue->top())));
651 mutable_queue->pop();
652 } 841 }
653 *mutable_queue = std::move(visited);
654 } 842 }
655 843
656 // static 844 // static
657 void TaskQueueImpl::TaskAsValueInto(const Task& task, 845 void TaskQueueImpl::TaskAsValueInto(const Task& task,
658 base::trace_event::TracedValue* state) { 846 base::trace_event::TracedValue* state) {
659 state->BeginDictionary(); 847 state->BeginDictionary();
660 state->SetString("posted_from", task.posted_from.ToString()); 848 state->SetString("posted_from", task.posted_from.ToString());
661 #ifndef NDEBUG 849 #ifndef NDEBUG
662 if (task.enqueue_order_set()) 850 if (task.enqueue_order_set())
663 state->SetInteger("enqueue_order", task.enqueue_order()); 851 state->SetInteger("enqueue_order", task.enqueue_order());
664 #else 852 #else
665 state->SetInteger("enqueue_order", task.enqueue_order()); 853 state->SetInteger("enqueue_order", task.enqueue_order());
666 #endif 854 #endif
667 state->SetInteger("sequence_num", task.sequence_num); 855 state->SetInteger("sequence_num", task.sequence_num);
668 state->SetBoolean("nestable", task.nestable); 856 state->SetBoolean("nestable", task.nestable);
669 state->SetBoolean("is_high_res", task.is_high_res); 857 state->SetBoolean("is_high_res", task.is_high_res);
670 state->SetBoolean("is_cancelled", task.task.IsCancelled());
671 state->SetDouble( 858 state->SetDouble(
672 "delayed_run_time", 859 "delayed_run_time",
673 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); 860 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L);
674 state->EndDictionary(); 861 state->EndDictionary();
675 } 862 }
676 863
677 } // namespace internal 864 } // namespace internal
678 } // namespace scheduler 865 } // namespace scheduler
679 } // namespace blink 866 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698