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 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |