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

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

Issue 2359493002: Prevent redundant DoWorks due to canceled delayed tasks (v2) (Closed)
Patch Set: Changes for Alexander Created 4 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
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"
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; 208 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
209 PushOntoDelayedIncomingQueueLocked( 209 PushOntoDelayedIncomingQueueLocked(
210 Task(from_here, task, time_domain_delayed_run_time, sequence_number, 210 Task(from_here, task, time_domain_delayed_run_time, sequence_number,
211 task_type != TaskType::NON_NESTABLE)); 211 task_type != TaskType::NON_NESTABLE));
212 } 212 }
213 return true; 213 return true;
214 } 214 }
215 215
216 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( 216 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread(
217 Task pending_task, base::TimeTicks now) { 217 Task pending_task, base::TimeTicks now) {
218 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
218 main_thread_only().task_queue_manager->DidQueueTask(pending_task); 219 main_thread_only().task_queue_manager->DidQueueTask(pending_task);
220 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
219 221
220 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. 222 // If |pending_task| is at the head of the queue, then make sure a wakeup
221 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 223 // is requested.
222 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); 224 if (main_thread_only().delayed_incoming_queue.top().delayed_run_time ==
223 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, 225 delayed_run_time) {
224 now); 226 main_thread_only().time_domain->ScheduleDelayedWork(
227 this, pending_task.delayed_run_time, now);
228 }
229
225 TraceQueueSize(false); 230 TraceQueueSize(false);
226 } 231 }
227 232
228 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { 233 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) {
229 any_thread().task_queue_manager->DidQueueTask(pending_task); 234 any_thread().task_queue_manager->DidQueueTask(pending_task);
230 235
231 int thread_hop_task_sequence_number = 236 int thread_hop_task_sequence_number =
232 any_thread().task_queue_manager->GetNextSequenceNumber(); 237 any_thread().task_queue_manager->GetNextSequenceNumber();
233 PushOntoImmediateIncomingQueueLocked( 238 PushOntoImmediateIncomingQueueLocked(
234 FROM_HERE, 239 FROM_HERE,
235 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, 240 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this,
236 base::Passed(&pending_task)), 241 base::Passed(&pending_task)),
237 base::TimeTicks(), 242 base::TimeTicks(),
238 thread_hop_task_sequence_number, 243 thread_hop_task_sequence_number,
239 false); 244 false);
240 } 245 }
241 246
247 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) {
248 DCHECK(main_thread_checker_.CalledOnValidThread());
249 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
250 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
251 if (delayed_run_time <= time_domain_now) {
252 // If |delayed_run_time| is in the past then push it onto the work queue
253 // immediately. To ensure the right task ordering we need to temporarily
254 // push it onto the |delayed_incoming_queue|.
255 delayed_run_time = time_domain_now;
256 pending_task.delayed_run_time = time_domain_now;
257 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
258 LazyNow lazy_now(time_domain_now);
259 WakeUpForDelayedWork(&lazy_now);
260 } else {
261 // If |delayed_run_time| is in the future we can queue it as normal.
262 PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task),
263 time_domain_now);
264 }
265 TraceQueueSize(false);
266 }
267
242 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( 268 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(
243 const tracked_objects::Location& posted_from, 269 const tracked_objects::Location& posted_from,
244 const base::Closure& task, 270 const base::Closure& task,
245 base::TimeTicks desired_run_time, 271 base::TimeTicks desired_run_time,
246 EnqueueOrder sequence_number, 272 EnqueueOrder sequence_number,
247 bool nestable) { 273 bool nestable) {
248 if (any_thread().immediate_incoming_queue.empty()) 274 if (any_thread().immediate_incoming_queue.empty())
249 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); 275 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
250 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make 276 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make
251 // it run. 277 // it run.
252 if (any_thread().immediate_incoming_queue.empty()) { 278 if (any_thread().immediate_incoming_queue.empty()) {
253 // There's no point posting a DoWork for a disabled queue, however we can 279 // 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. 280 // only tell if it's disabled from the main thread.
255 if (base::PlatformThread::CurrentId() == thread_id_) { 281 if (base::PlatformThread::CurrentId() == thread_id_) {
256 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) 282 if (main_thread_only().is_enabled && !BlockedByFenceLocked())
257 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 283 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
258 } else { 284 } else {
259 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 285 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
260 } 286 }
261 } 287 }
262 any_thread().immediate_incoming_queue.emplace( 288 any_thread().immediate_incoming_queue.emplace(
263 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber); 289 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber);
264 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back()); 290 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back());
265 TraceQueueSize(true); 291 TraceQueueSize(true);
266 } 292 }
267 293
268 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) {
269 DCHECK(main_thread_checker_.CalledOnValidThread());
270 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
271 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
272 // Make sure |delayed_run_time| isn't in the past.
273 if (delayed_run_time < time_domain_now) {
274 delayed_run_time = time_domain_now;
275 pending_task.delayed_run_time = time_domain_now;
276 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
277 LazyNow lazy_now(time_domain_now);
278 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now);
279 } else {
280 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
281 main_thread_only().time_domain->ScheduleDelayedWork(
282 this, delayed_run_time, main_thread_only().time_domain->Now());
283 }
284 TraceQueueSize(false);
285 }
286
287 void TaskQueueImpl::SetQueueEnabled(bool enabled) { 294 void TaskQueueImpl::SetQueueEnabled(bool enabled) {
288 if (main_thread_only().is_enabled == enabled) 295 if (main_thread_only().is_enabled == enabled)
289 return; 296 return;
290 main_thread_only().is_enabled = enabled; 297 main_thread_only().is_enabled = enabled;
291 if (!main_thread_only().task_queue_manager) 298 if (!main_thread_only().task_queue_manager)
292 return; 299 return;
293 if (enabled) { 300 if (enabled) {
294 // Note it's the job of the selector to tell the TaskQueueManager if 301 // Note it's the job of the selector to tell the TaskQueueManager if
295 // a DoWork needs posting. 302 // a DoWork needs posting.
296 main_thread_only().task_queue_manager->selector_.EnableQueue(this); 303 main_thread_only().task_queue_manager->selector_.EnableQueue(this);
(...skipping 30 matching lines...) Expand all
327 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= 334 main_thread_only().delayed_incoming_queue.top().delayed_run_time <=
328 main_thread_only().time_domain->CreateLazyNow().Now()) { 335 main_thread_only().time_domain->CreateLazyNow().Now()) {
329 return true; 336 return true;
330 } 337 }
331 338
332 // Finally tasks on |immediate_incoming_queue| count as immediate work. 339 // Finally tasks on |immediate_incoming_queue| count as immediate work.
333 base::AutoLock lock(any_thread_lock_); 340 base::AutoLock lock(any_thread_lock_);
334 return !any_thread().immediate_incoming_queue.empty(); 341 return !any_thread().immediate_incoming_queue.empty();
335 } 342 }
336 343
337 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { 344 void TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) {
338 // Enqueue all delayed tasks that should be running now, skipping any that 345 // Enqueue all delayed tasks that should be running now, skipping any that
339 // have been canceled. 346 // have been canceled.
340 while (!main_thread_only().delayed_incoming_queue.empty()) { 347 while (!main_thread_only().delayed_incoming_queue.empty()) {
341 // TODO(alexclarke): Use extract() when C++17 is allowed.
342 Task& task = 348 Task& task =
343 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); 349 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top());
344 if (task.task.IsCancelled()) { 350 if (task.task.IsCancelled()) {
345 main_thread_only().delayed_incoming_queue.pop(); 351 main_thread_only().delayed_incoming_queue.pop();
346 continue; 352 continue;
347 } 353 }
348 if (task.delayed_run_time > lazy_now->Now()) 354 if (task.delayed_run_time > lazy_now->Now())
349 break; 355 break;
350 task.set_enqueue_order( 356 task.set_enqueue_order(
351 main_thread_only().task_queue_manager->GetNextSequenceNumber()); 357 main_thread_only().task_queue_manager->GetNextSequenceNumber());
352 main_thread_only().delayed_work_queue->Push(std::move(task)); 358 main_thread_only().delayed_work_queue->Push(std::move(task));
353 main_thread_only().delayed_incoming_queue.pop(); 359 main_thread_only().delayed_incoming_queue.pop();
354 } 360 }
361
362 // Make sure the next wake up is scheduled.
363 if (!main_thread_only().delayed_incoming_queue.empty()) {
364 main_thread_only().time_domain->ScheduleDelayedWork(
365 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time,
366 lazy_now->Now());
367 }
355 } 368 }
356 369
357 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() { 370 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() {
358 if (!main_thread_only().task_queue_manager) 371 if (!main_thread_only().task_queue_manager)
359 return false; 372 return false;
360 373
361 if (!main_thread_only().immediate_work_queue->Empty()) 374 if (!main_thread_only().immediate_work_queue->Empty())
362 return true; 375 return true;
363 376
364 base::AutoLock lock(any_thread_lock_); 377 base::AutoLock lock(any_thread_lock_);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 main_thread_only().immediate_work_queue->Size()); 458 main_thread_only().immediate_work_queue->Size());
446 state->SetInteger("delayed_work_queue_size", 459 state->SetInteger("delayed_work_queue_size",
447 main_thread_only().delayed_work_queue->Size()); 460 main_thread_only().delayed_work_queue->Size());
448 if (!main_thread_only().delayed_incoming_queue.empty()) { 461 if (!main_thread_only().delayed_incoming_queue.empty()) {
449 base::TimeDelta delay_to_next_task = 462 base::TimeDelta delay_to_next_task =
450 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - 463 (main_thread_only().delayed_incoming_queue.top().delayed_run_time -
451 main_thread_only().time_domain->CreateLazyNow().Now()); 464 main_thread_only().time_domain->CreateLazyNow().Now());
452 state->SetDouble("delay_to_next_task_ms", 465 state->SetDouble("delay_to_next_task_ms",
453 delay_to_next_task.InMillisecondsF()); 466 delay_to_next_task.InMillisecondsF());
454 } 467 }
468 if (main_thread_only().current_fence)
469 state->SetInteger("current_fence", main_thread_only().current_fence);
455 if (verbose_tracing_enabled) { 470 if (verbose_tracing_enabled) {
456 state->BeginArray("immediate_incoming_queue"); 471 state->BeginArray("immediate_incoming_queue");
457 QueueAsValueInto(any_thread().immediate_incoming_queue, state); 472 QueueAsValueInto(any_thread().immediate_incoming_queue, state);
458 state->EndArray(); 473 state->EndArray();
459 state->BeginArray("delayed_work_queue"); 474 state->BeginArray("delayed_work_queue");
460 main_thread_only().delayed_work_queue->AsValueInto(state); 475 main_thread_only().delayed_work_queue->AsValueInto(state);
461 state->EndArray(); 476 state->EndArray();
462 state->BeginArray("immediate_work_queue"); 477 state->BeginArray("immediate_work_queue");
463 main_thread_only().immediate_work_queue->AsValueInto(state); 478 main_thread_only().immediate_work_queue->AsValueInto(state);
464 state->EndArray(); 479 state->EndArray();
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 state->SetBoolean("is_cancelled", task.task.IsCancelled()); 685 state->SetBoolean("is_cancelled", task.task.IsCancelled());
671 state->SetDouble( 686 state->SetDouble(
672 "delayed_run_time", 687 "delayed_run_time",
673 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); 688 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L);
674 state->EndDictionary(); 689 state->EndDictionary();
675 } 690 }
676 691
677 } // namespace internal 692 } // namespace internal
678 } // namespace scheduler 693 } // namespace scheduler
679 } // namespace blink 694 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698