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