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

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

Issue 2320403003: Prevent redundant DoWorks due to canceled delayed tasks (Closed)
Patch Set: Added a commant. 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"
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 main_thread_only().task_queue_manager->DidQueueTask(pending_task); 218 main_thread_only().task_queue_manager->DidQueueTask(pending_task);
219 219
220 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue.
221 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 220 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
221 bool queue_was_empty = main_thread_only().delayed_incoming_queue.empty();
222 base::TimeTicks previous_next_run_time;
223 if (!queue_was_empty) {
224 previous_next_run_time =
225 main_thread_only().delayed_incoming_queue.top().delayed_run_time;
226 }
222 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); 227 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
223 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, 228
224 now); 229 // Make sure the next wakeup (and only the next wakeup) is registered with the
230 // TimeDomain.
231 if (queue_was_empty || delayed_run_time < previous_next_run_time) {
232 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time,
233 now);
234 if (!queue_was_empty) {
235 main_thread_only().time_domain->CancelDelayedWork(this,
236 previous_next_run_time);
237 }
238 }
225 TraceQueueSize(false); 239 TraceQueueSize(false);
226 } 240 }
227 241
228 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { 242 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) {
229 any_thread().task_queue_manager->DidQueueTask(pending_task); 243 any_thread().task_queue_manager->DidQueueTask(pending_task);
230 244
231 int thread_hop_task_sequence_number = 245 int thread_hop_task_sequence_number =
232 any_thread().task_queue_manager->GetNextSequenceNumber(); 246 any_thread().task_queue_manager->GetNextSequenceNumber();
233 PushOntoImmediateIncomingQueueLocked( 247 PushOntoImmediateIncomingQueueLocked(
234 FROM_HERE, 248 FROM_HERE,
235 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, 249 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this,
236 base::Passed(&pending_task)), 250 base::Passed(&pending_task)),
237 base::TimeTicks(), 251 base::TimeTicks(),
238 thread_hop_task_sequence_number, 252 thread_hop_task_sequence_number,
239 false); 253 false);
240 } 254 }
241 255
242 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( 256 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(
243 const tracked_objects::Location& posted_from, 257 const tracked_objects::Location& posted_from,
244 const base::Closure& task, 258 const base::Closure& task,
245 base::TimeTicks desired_run_time, 259 base::TimeTicks desired_run_time,
246 EnqueueOrder sequence_number, 260 EnqueueOrder sequence_number,
247 bool nestable) { 261 bool nestable) {
248 if (any_thread().immediate_incoming_queue.empty()) 262 if (any_thread().immediate_incoming_queue.empty())
249 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); 263 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
250 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make 264 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make
251 // it run. 265 // it run.
252 if (any_thread().immediate_incoming_queue.empty()) { 266 if (any_thread().immediate_incoming_queue.empty()) {
253 // There's no point posting a DoWork for a disabled queue, however we can 267 // 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. 268 // only tell if it's disabled from the main thread.
255 if (base::PlatformThread::CurrentId() == thread_id_) { 269 if (base::PlatformThread::CurrentId() == thread_id_) {
256 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) 270 if (main_thread_only().is_enabled && !BlockedByFenceLocked())
257 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 271 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
258 } else { 272 } else {
259 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 273 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
260 } 274 }
261 } 275 }
262 any_thread().immediate_incoming_queue.emplace( 276 any_thread().immediate_incoming_queue.emplace(
263 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber); 277 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()); 278 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back());
265 TraceQueueSize(true); 279 TraceQueueSize(true);
266 } 280 }
267 281
268 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { 282 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) {
269 DCHECK(main_thread_checker_.CalledOnValidThread()); 283 DCHECK(main_thread_checker_.CalledOnValidThread());
270 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 284 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
271 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); 285 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) { 286 if (delayed_run_time < time_domain_now) {
287 // If |delayed_run_time| is in the past then push it onto the work queue
288 // immediately. To ensure the right task ordering we need to temporarily
289 // push it onto the |delayed_incoming_queue|.
274 delayed_run_time = time_domain_now; 290 delayed_run_time = time_domain_now;
275 pending_task.delayed_run_time = time_domain_now; 291 pending_task.delayed_run_time = time_domain_now;
276 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); 292 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
277 LazyNow lazy_now(time_domain_now); 293 LazyNow lazy_now(time_domain_now);
278 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now); 294 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now);
279 } else { 295 } else {
280 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); 296 // If |delayed_run_time| is in the future we can queue it as normal.
281 main_thread_only().time_domain->ScheduleDelayedWork( 297 PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task),
282 this, delayed_run_time, main_thread_only().time_domain->Now()); 298 time_domain_now);
283 } 299 }
284 TraceQueueSize(false); 300 TraceQueueSize(false);
285 } 301 }
286 302
287 void TaskQueueImpl::SetQueueEnabled(bool enabled) { 303 void TaskQueueImpl::SetQueueEnabled(bool enabled) {
288 if (main_thread_only().is_enabled == enabled) 304 if (main_thread_only().is_enabled == enabled)
289 return; 305 return;
290 main_thread_only().is_enabled = enabled; 306 main_thread_only().is_enabled = enabled;
291 if (!main_thread_only().task_queue_manager) 307 if (!main_thread_only().task_queue_manager)
292 return; 308 return;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 main_thread_only().delayed_incoming_queue.pop(); 361 main_thread_only().delayed_incoming_queue.pop();
346 continue; 362 continue;
347 } 363 }
348 if (task.delayed_run_time > lazy_now->Now()) 364 if (task.delayed_run_time > lazy_now->Now())
349 break; 365 break;
350 task.set_enqueue_order( 366 task.set_enqueue_order(
351 main_thread_only().task_queue_manager->GetNextSequenceNumber()); 367 main_thread_only().task_queue_manager->GetNextSequenceNumber());
352 main_thread_only().delayed_work_queue->Push(std::move(task)); 368 main_thread_only().delayed_work_queue->Push(std::move(task));
353 main_thread_only().delayed_incoming_queue.pop(); 369 main_thread_only().delayed_incoming_queue.pop();
354 } 370 }
371 // Make sure the next wake up is scheduled.
372 if (!main_thread_only().delayed_incoming_queue.empty()) {
373 main_thread_only().time_domain->ScheduleDelayedWork(
374 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time,
375 lazy_now->Now());
376 }
355 } 377 }
356 378
357 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() { 379 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() {
358 if (!main_thread_only().task_queue_manager) 380 if (!main_thread_only().task_queue_manager)
359 return false; 381 return false;
360 382
361 if (!main_thread_only().immediate_work_queue->Empty()) 383 if (!main_thread_only().immediate_work_queue->Empty())
362 return true; 384 return true;
363 385
364 base::AutoLock lock(any_thread_lock_); 386 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()); 467 main_thread_only().immediate_work_queue->Size());
446 state->SetInteger("delayed_work_queue_size", 468 state->SetInteger("delayed_work_queue_size",
447 main_thread_only().delayed_work_queue->Size()); 469 main_thread_only().delayed_work_queue->Size());
448 if (!main_thread_only().delayed_incoming_queue.empty()) { 470 if (!main_thread_only().delayed_incoming_queue.empty()) {
449 base::TimeDelta delay_to_next_task = 471 base::TimeDelta delay_to_next_task =
450 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - 472 (main_thread_only().delayed_incoming_queue.top().delayed_run_time -
451 main_thread_only().time_domain->CreateLazyNow().Now()); 473 main_thread_only().time_domain->CreateLazyNow().Now());
452 state->SetDouble("delay_to_next_task_ms", 474 state->SetDouble("delay_to_next_task_ms",
453 delay_to_next_task.InMillisecondsF()); 475 delay_to_next_task.InMillisecondsF());
454 } 476 }
477 if (main_thread_only().current_fence)
478 state->SetInteger("current_fence", main_thread_only().current_fence);
455 if (verbose_tracing_enabled) { 479 if (verbose_tracing_enabled) {
456 state->BeginArray("immediate_incoming_queue"); 480 state->BeginArray("immediate_incoming_queue");
457 QueueAsValueInto(any_thread().immediate_incoming_queue, state); 481 QueueAsValueInto(any_thread().immediate_incoming_queue, state);
458 state->EndArray(); 482 state->EndArray();
459 state->BeginArray("delayed_work_queue"); 483 state->BeginArray("delayed_work_queue");
460 main_thread_only().delayed_work_queue->AsValueInto(state); 484 main_thread_only().delayed_work_queue->AsValueInto(state);
461 state->EndArray(); 485 state->EndArray();
462 state->BeginArray("immediate_work_queue"); 486 state->BeginArray("immediate_work_queue");
463 main_thread_only().immediate_work_queue->AsValueInto(state); 487 main_thread_only().immediate_work_queue->AsValueInto(state);
464 state->EndArray(); 488 state->EndArray();
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 state->SetBoolean("is_cancelled", task.task.IsCancelled()); 694 state->SetBoolean("is_cancelled", task.task.IsCancelled());
671 state->SetDouble( 695 state->SetDouble(
672 "delayed_run_time", 696 "delayed_run_time",
673 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); 697 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L);
674 state->EndDictionary(); 698 state->EndDictionary();
675 } 699 }
676 700
677 } // namespace internal 701 } // namespace internal
678 } // namespace scheduler 702 } // namespace scheduler
679 } // namespace blink 703 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698