| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 // destructor calls UnregisterTaskQueue on all task queues. | 102 // destructor calls UnregisterTaskQueue on all task queues. |
| 103 DCHECK(any_thread().task_queue_manager == nullptr) | 103 DCHECK(any_thread().task_queue_manager == nullptr) |
| 104 << "UnregisterTaskQueue must be called first!"; | 104 << "UnregisterTaskQueue must be called first!"; |
| 105 #endif | 105 #endif |
| 106 } | 106 } |
| 107 | 107 |
| 108 TaskQueueImpl::Task::Task() | 108 TaskQueueImpl::Task::Task() |
| 109 : PendingTask(tracked_objects::Location(), | 109 : PendingTask(tracked_objects::Location(), |
| 110 base::Closure(), | 110 base::Closure(), |
| 111 base::TimeTicks(), | 111 base::TimeTicks(), |
| 112 true), | 112 true) { |
| 113 #ifndef NDEBUG | |
| 114 enqueue_order_set_(false), | |
| 115 #endif | |
| 116 enqueue_order_(0) { | |
| 117 sequence_num = 0; | 113 sequence_num = 0; |
| 118 } | 114 } |
| 119 | 115 |
| 120 TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from, | 116 TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from, |
| 121 base::OnceClosure task, | 117 base::OnceClosure task, |
| 122 base::TimeTicks desired_run_time, | 118 EnqueueOrder enqueue_order, |
| 123 EnqueueOrder sequence_number, | |
| 124 bool nestable) | 119 bool nestable) |
| 125 : PendingTask(posted_from, std::move(task), desired_run_time, nestable), | 120 : PendingTask(posted_from, |
| 126 #ifndef NDEBUG | 121 std::move(task), |
| 127 enqueue_order_set_(false), | 122 enqueue_order.delayed_run_time, |
| 128 #endif | 123 nestable), |
| 129 enqueue_order_(0) { | |
| 130 sequence_num = sequence_number; | |
| 131 } | |
| 132 | |
| 133 TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from, | |
| 134 base::OnceClosure task, | |
| 135 base::TimeTicks desired_run_time, | |
| 136 EnqueueOrder sequence_number, | |
| 137 bool nestable, | |
| 138 EnqueueOrder enqueue_order) | |
| 139 : PendingTask(posted_from, std::move(task), desired_run_time, nestable), | |
| 140 #ifndef NDEBUG | |
| 141 enqueue_order_set_(true), | |
| 142 #endif | |
| 143 enqueue_order_(enqueue_order) { | 124 enqueue_order_(enqueue_order) { |
| 144 sequence_num = sequence_number; | 125 // Note: these properties are only used for tracing. |
| 126 sequence_num = static_cast<int>(enqueue_order.sequence_num); |
| 127 delayed_run_time = enqueue_order.delayed_run_time; |
| 145 } | 128 } |
| 146 | 129 |
| 147 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, | 130 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
| 148 TimeDomain* time_domain) | 131 TimeDomain* time_domain) |
| 149 : task_queue_manager(task_queue_manager), | 132 : task_queue_manager(task_queue_manager), |
| 150 time_domain(time_domain), | 133 time_domain(time_domain), |
| 151 observer(nullptr) {} | 134 observer(nullptr) {} |
| 152 | 135 |
| 153 TaskQueueImpl::AnyThread::~AnyThread() {} | 136 TaskQueueImpl::AnyThread::~AnyThread() {} |
| 154 | 137 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 const tracked_objects::Location& from_here, | 206 const tracked_objects::Location& from_here, |
| 224 base::OnceClosure task, | 207 base::OnceClosure task, |
| 225 TaskType task_type) { | 208 TaskType task_type) { |
| 226 // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167 | 209 // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167 |
| 227 // for details. | 210 // for details. |
| 228 CHECK(task); | 211 CHECK(task); |
| 229 base::AutoLock lock(any_thread_lock_); | 212 base::AutoLock lock(any_thread_lock_); |
| 230 if (!any_thread().task_queue_manager) | 213 if (!any_thread().task_queue_manager) |
| 231 return false; | 214 return false; |
| 232 | 215 |
| 233 EnqueueOrder sequence_number = | 216 EnqueueOrder enqueue_order = |
| 234 any_thread().task_queue_manager->GetNextSequenceNumber(); | 217 any_thread().task_queue_manager->GetNextEnqueueOrder(base::TimeTicks()); |
| 235 | 218 |
| 236 PushOntoImmediateIncomingQueueLocked(from_here, std::move(task), | 219 PushOntoImmediateIncomingQueueLocked(from_here, std::move(task), |
| 237 base::TimeTicks(), sequence_number, | 220 enqueue_order, |
| 238 task_type != TaskType::NON_NESTABLE); | 221 task_type != TaskType::NON_NESTABLE); |
| 239 return true; | 222 return true; |
| 240 } | 223 } |
| 241 | 224 |
| 242 bool TaskQueueImpl::PostDelayedTaskImpl( | 225 bool TaskQueueImpl::PostDelayedTaskImpl( |
| 243 const tracked_objects::Location& from_here, | 226 const tracked_objects::Location& from_here, |
| 244 base::OnceClosure task, | 227 base::OnceClosure task, |
| 245 base::TimeDelta delay, | 228 base::TimeDelta delay, |
| 246 TaskType task_type) { | 229 TaskType task_type) { |
| 247 // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167 | 230 // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167 |
| 248 // for details. | 231 // for details. |
| 249 CHECK(task); | 232 CHECK(task); |
| 250 DCHECK_GT(delay, base::TimeDelta()); | 233 DCHECK_GT(delay, base::TimeDelta()); |
| 251 if (base::PlatformThread::CurrentId() == thread_id_) { | 234 if (base::PlatformThread::CurrentId() == thread_id_) { |
| 252 // Lock-free fast path for delayed tasks posted from the main thread. | 235 // Lock-free fast path for delayed tasks posted from the main thread. |
| 253 if (!main_thread_only().task_queue_manager) | 236 if (!main_thread_only().task_queue_manager) |
| 254 return false; | 237 return false; |
| 255 | 238 |
| 256 EnqueueOrder sequence_number = | |
| 257 main_thread_only().task_queue_manager->GetNextSequenceNumber(); | |
| 258 | |
| 259 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); | 239 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); |
| 260 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; | 240 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; |
| 241 EnqueueOrder enqueue_order = |
| 242 main_thread_only().task_queue_manager->GetNextEnqueueOrder( |
| 243 time_domain_delayed_run_time); |
| 261 PushOntoDelayedIncomingQueueFromMainThread( | 244 PushOntoDelayedIncomingQueueFromMainThread( |
| 262 Task(from_here, std::move(task), time_domain_delayed_run_time, | 245 Task(from_here, std::move(task), enqueue_order, |
| 263 sequence_number, task_type != TaskType::NON_NESTABLE), | 246 task_type != TaskType::NON_NESTABLE), |
| 264 time_domain_now); | 247 time_domain_now); |
| 265 } else { | 248 } else { |
| 266 // NOTE posting a delayed task from a different thread is not expected to | 249 // NOTE posting a delayed task from a different thread is not expected to |
| 267 // be common. This pathway is less optimal than perhaps it could be | 250 // be common. This pathway is less optimal than perhaps it could be |
| 268 // because it causes two main thread tasks to be run. Should this | 251 // because it causes two main thread tasks to be run. Should this |
| 269 // assumption prove to be false in future, we may need to revisit this. | 252 // assumption prove to be false in future, we may need to revisit this. |
| 270 base::AutoLock lock(any_thread_lock_); | 253 base::AutoLock lock(any_thread_lock_); |
| 271 if (!any_thread().task_queue_manager) | 254 if (!any_thread().task_queue_manager) |
| 272 return false; | 255 return false; |
| 273 | 256 |
| 274 EnqueueOrder sequence_number = | |
| 275 any_thread().task_queue_manager->GetNextSequenceNumber(); | |
| 276 | |
| 277 base::TimeTicks time_domain_now = any_thread().time_domain->Now(); | 257 base::TimeTicks time_domain_now = any_thread().time_domain->Now(); |
| 278 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; | 258 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; |
| 259 EnqueueOrder enqueue_order = |
| 260 any_thread().task_queue_manager->GetNextEnqueueOrder( |
| 261 time_domain_delayed_run_time); |
| 279 PushOntoDelayedIncomingQueueLocked( | 262 PushOntoDelayedIncomingQueueLocked( |
| 280 Task(from_here, std::move(task), time_domain_delayed_run_time, | 263 Task(from_here, std::move(task), enqueue_order, |
| 281 sequence_number, task_type != TaskType::NON_NESTABLE)); | 264 task_type != TaskType::NON_NESTABLE)); |
| 282 } | 265 } |
| 283 return true; | 266 return true; |
| 284 } | 267 } |
| 285 | 268 |
| 286 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( | 269 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( |
| 287 Task pending_task, base::TimeTicks now) { | 270 Task pending_task, base::TimeTicks now) { |
| 288 DelayedWakeUp wake_up = pending_task.delayed_wake_up(); | 271 DelayedWakeUp wake_up = pending_task.delayed_wake_up(); |
| 289 main_thread_only().task_queue_manager->DidQueueTask(pending_task); | 272 main_thread_only().task_queue_manager->DidQueueTask(pending_task); |
| 290 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 273 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); |
| 291 | 274 |
| 292 // If |pending_task| is at the head of the queue, then make sure a wake-up | 275 // If |pending_task| is at the head of the queue, then make sure a wake-up |
| 293 // is requested if the queue is enabled. Note we still want to schedule a | 276 // is requested if the queue is enabled. Note we still want to schedule a |
| 294 // wake-up even if blocked by a fence, because we'd break throttling logic | 277 // wake-up even if blocked by a fence, because we'd break throttling logic |
| 295 // otherwise. | 278 // otherwise. |
| 296 DelayedWakeUp new_wake_up = | 279 DelayedWakeUp new_wake_up = |
| 297 main_thread_only().delayed_incoming_queue.top().delayed_wake_up(); | 280 main_thread_only().delayed_incoming_queue.top().delayed_wake_up(); |
| 298 if (wake_up.time == new_wake_up.time && | 281 if (wake_up.time == new_wake_up.time && |
| 299 wake_up.sequence_num == new_wake_up.sequence_num) { | 282 wake_up.sequence_num == new_wake_up.sequence_num) { |
| 300 ScheduleDelayedWorkInTimeDomain(now); | 283 ScheduleDelayedWorkInTimeDomain(now); |
| 301 } | 284 } |
| 302 | 285 |
| 303 TraceQueueSize(); | 286 TraceQueueSize(); |
| 304 } | 287 } |
| 305 | 288 |
| 306 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { | 289 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { |
| 307 any_thread().task_queue_manager->DidQueueTask(pending_task); | 290 any_thread().task_queue_manager->DidQueueTask(pending_task); |
| 308 | 291 |
| 309 int thread_hop_task_sequence_number = | 292 EnqueueOrder thread_hop_task_enqueue_order = |
| 310 any_thread().task_queue_manager->GetNextSequenceNumber(); | 293 any_thread().task_queue_manager->GetNextEnqueueOrder(base::TimeTicks()); |
| 311 PushOntoImmediateIncomingQueueLocked( | 294 PushOntoImmediateIncomingQueueLocked( |
| 312 FROM_HERE, | 295 FROM_HERE, |
| 313 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 296 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
| 314 base::Passed(&pending_task)), | 297 base::Passed(&pending_task)), |
| 315 base::TimeTicks(), | 298 thread_hop_task_enqueue_order, false); |
| 316 thread_hop_task_sequence_number, | |
| 317 false); | |
| 318 } | 299 } |
| 319 | 300 |
| 320 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { | 301 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { |
| 321 DCHECK(main_thread_checker_.CalledOnValidThread()); | 302 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 322 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 303 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; |
| 323 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); | 304 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); |
| 324 if (delayed_run_time <= time_domain_now) { | 305 if (delayed_run_time <= time_domain_now) { |
| 325 // If |delayed_run_time| is in the past then push it onto the work queue | 306 // If |delayed_run_time| is in the past then push it onto the work queue |
| 326 // immediately. To ensure the right task ordering we need to temporarily | 307 // immediately. To ensure the right task ordering we need to temporarily |
| 327 // push it onto the |delayed_incoming_queue|. | 308 // push it onto the |delayed_incoming_queue|. |
| 328 delayed_run_time = time_domain_now; | 309 delayed_run_time = time_domain_now; |
| 329 pending_task.delayed_run_time = time_domain_now; | 310 pending_task.delayed_run_time = time_domain_now; |
| 330 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 311 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); |
| 331 LazyNow lazy_now(time_domain_now); | 312 LazyNow lazy_now(time_domain_now); |
| 332 WakeUpForDelayedWork(&lazy_now); | 313 WakeUpForDelayedWork(&lazy_now); |
| 333 } else { | 314 } else { |
| 334 // If |delayed_run_time| is in the future we can queue it as normal. | 315 // If |delayed_run_time| is in the future we can queue it as normal. |
| 335 PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task), | 316 PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task), |
| 336 time_domain_now); | 317 time_domain_now); |
| 337 } | 318 } |
| 338 TraceQueueSize(); | 319 TraceQueueSize(); |
| 339 } | 320 } |
| 340 | 321 |
| 341 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( | 322 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( |
| 342 const tracked_objects::Location& posted_from, | 323 const tracked_objects::Location& posted_from, |
| 343 base::OnceClosure task, | 324 base::OnceClosure task, |
| 344 base::TimeTicks desired_run_time, | 325 EnqueueOrder enqueue_order, |
| 345 EnqueueOrder sequence_number, | |
| 346 bool nestable) { | 326 bool nestable) { |
| 347 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make | 327 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |
| 348 // it run. | 328 // it run. |
| 349 bool was_immediate_incoming_queue_empty; | 329 bool was_immediate_incoming_queue_empty; |
| 350 | 330 |
| 351 { | 331 { |
| 352 base::AutoLock lock(immediate_incoming_queue_lock_); | 332 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 353 was_immediate_incoming_queue_empty = immediate_incoming_queue().empty(); | 333 was_immediate_incoming_queue_empty = immediate_incoming_queue().empty(); |
| 354 immediate_incoming_queue().emplace_back(posted_from, std::move(task), | 334 immediate_incoming_queue().emplace_back(posted_from, std::move(task), |
| 355 desired_run_time, sequence_number, | 335 enqueue_order, nestable); |
| 356 nestable, sequence_number); | |
| 357 any_thread().task_queue_manager->DidQueueTask( | 336 any_thread().task_queue_manager->DidQueueTask( |
| 358 immediate_incoming_queue().back()); | 337 immediate_incoming_queue().back()); |
| 359 } | 338 } |
| 360 | 339 |
| 361 if (was_immediate_incoming_queue_empty) { | 340 if (was_immediate_incoming_queue_empty) { |
| 362 // However there's no point posting a DoWork for a blocked queue. NB we can | 341 // However there's no point posting a DoWork for a blocked queue. NB we can |
| 363 // only tell if it's disabled from the main thread. | 342 // only tell if it's disabled from the main thread. |
| 364 bool queue_is_blocked = | 343 bool queue_is_blocked = |
| 365 RunsTasksOnCurrentThread() && | 344 RunsTasksOnCurrentThread() && |
| 366 (!IsQueueEnabled() || main_thread_only().current_fence); | 345 (!IsQueueEnabled() || main_thread_only().current_fence); |
| 367 any_thread().task_queue_manager->OnQueueHasIncomingImmediateWork( | 346 any_thread().task_queue_manager->OnQueueHasIncomingImmediateWork( |
| 368 this, sequence_number, queue_is_blocked); | 347 this, enqueue_order, queue_is_blocked); |
| 369 if (any_thread().observer) | 348 if (any_thread().observer) |
| 370 any_thread().observer->OnQueueNextWakeUpChanged(this, desired_run_time); | 349 any_thread().observer->OnQueueNextWakeUpChanged( |
| 350 this, enqueue_order.delayed_run_time); |
| 371 } | 351 } |
| 372 | 352 |
| 373 TraceQueueSize(); | 353 TraceQueueSize(); |
| 374 } | 354 } |
| 375 | 355 |
| 376 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { | 356 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { |
| 377 if (!main_thread_only().immediate_work_queue->Empty()) | 357 if (!main_thread_only().immediate_work_queue->Empty()) |
| 378 return; | 358 return; |
| 379 | 359 |
| 380 main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue(); | 360 main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // have been canceled. | 423 // have been canceled. |
| 444 while (!main_thread_only().delayed_incoming_queue.empty()) { | 424 while (!main_thread_only().delayed_incoming_queue.empty()) { |
| 445 Task& task = | 425 Task& task = |
| 446 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); | 426 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); |
| 447 if (task.task.IsCancelled()) { | 427 if (task.task.IsCancelled()) { |
| 448 main_thread_only().delayed_incoming_queue.pop(); | 428 main_thread_only().delayed_incoming_queue.pop(); |
| 449 continue; | 429 continue; |
| 450 } | 430 } |
| 451 if (task.delayed_run_time > lazy_now->Now()) | 431 if (task.delayed_run_time > lazy_now->Now()) |
| 452 break; | 432 break; |
| 453 task.set_enqueue_order( | |
| 454 main_thread_only().task_queue_manager->GetNextSequenceNumber()); | |
| 455 main_thread_only().delayed_work_queue->Push(std::move(task)); | 433 main_thread_only().delayed_work_queue->Push(std::move(task)); |
| 456 main_thread_only().delayed_incoming_queue.pop(); | 434 main_thread_only().delayed_incoming_queue.pop(); |
| 457 } | 435 } |
| 458 | 436 |
| 459 // Make sure the next wake up is scheduled. | 437 // Make sure the next wake up is scheduled. |
| 460 if (!main_thread_only().delayed_incoming_queue.empty()) { | 438 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 461 return main_thread_only().delayed_incoming_queue.top().delayed_wake_up(); | 439 return main_thread_only().delayed_incoming_queue.top().delayed_wake_up(); |
| 462 } | 440 } |
| 463 | 441 |
| 464 return base::nullopt; | 442 return base::nullopt; |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 | 596 |
| 619 void TaskQueueImpl::SetBlameContext( | 597 void TaskQueueImpl::SetBlameContext( |
| 620 base::trace_event::BlameContext* blame_context) { | 598 base::trace_event::BlameContext* blame_context) { |
| 621 main_thread_only().blame_context = blame_context; | 599 main_thread_only().blame_context = blame_context; |
| 622 } | 600 } |
| 623 | 601 |
| 624 void TaskQueueImpl::InsertFence(TaskQueue::InsertFencePosition position) { | 602 void TaskQueueImpl::InsertFence(TaskQueue::InsertFencePosition position) { |
| 625 if (!main_thread_only().task_queue_manager) | 603 if (!main_thread_only().task_queue_manager) |
| 626 return; | 604 return; |
| 627 | 605 |
| 628 EnqueueOrder previous_fence = main_thread_only().current_fence; | 606 SequenceNumber previous_fence = main_thread_only().current_fence; |
| 629 main_thread_only().current_fence = | 607 main_thread_only().current_fence = |
| 630 position == TaskQueue::InsertFencePosition::NOW | 608 position == TaskQueue::InsertFencePosition::NOW |
| 631 ? main_thread_only().task_queue_manager->GetNextSequenceNumber() | 609 ? main_thread_only() |
| 632 : static_cast<EnqueueOrder>(EnqueueOrderValues::BLOCKING_FENCE); | 610 .task_queue_manager->GetNextEnqueueOrder(base::TimeTicks()) |
| 611 .sequence_num |
| 612 : static_cast<SequenceNumber>( |
| 613 EnqueueOrderSequenceNumberValues::BLOCKING_FENCE); |
| 633 | 614 |
| 634 // Tasks posted after this point will have a strictly higher enqueue order | 615 // Tasks posted after this point will have a strictly higher enqueue order |
| 635 // and will be blocked from running. | 616 // and will be blocked from running. |
| 636 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( | 617 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( |
| 637 main_thread_only().current_fence); | 618 main_thread_only().current_fence); |
| 638 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( | 619 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( |
| 639 main_thread_only().current_fence); | 620 main_thread_only().current_fence); |
| 640 | 621 |
| 641 if (!task_unblocked && previous_fence && | 622 if (!task_unblocked && previous_fence && |
| 642 previous_fence < main_thread_only().current_fence) { | 623 previous_fence < main_thread_only().current_fence) { |
| 643 base::AutoLock lock(immediate_incoming_queue_lock_); | 624 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 644 if (!immediate_incoming_queue().empty() && | 625 if (!immediate_incoming_queue().empty() && |
| 645 immediate_incoming_queue().front().enqueue_order() > previous_fence && | 626 immediate_incoming_queue().front().enqueue_order().sequence_num > |
| 646 immediate_incoming_queue().front().enqueue_order() < | 627 previous_fence && |
| 628 immediate_incoming_queue().front().enqueue_order().sequence_num < |
| 647 main_thread_only().current_fence) { | 629 main_thread_only().current_fence) { |
| 648 task_unblocked = true; | 630 task_unblocked = true; |
| 649 } | 631 } |
| 650 } | 632 } |
| 651 | 633 |
| 652 if (IsQueueEnabled() && task_unblocked) { | 634 if (IsQueueEnabled() && task_unblocked) { |
| 653 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 635 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 654 FROM_HERE); | 636 FROM_HERE); |
| 655 } | 637 } |
| 656 } | 638 } |
| 657 | 639 |
| 658 void TaskQueueImpl::RemoveFence() { | 640 void TaskQueueImpl::RemoveFence() { |
| 659 if (!main_thread_only().task_queue_manager) | 641 if (!main_thread_only().task_queue_manager) |
| 660 return; | 642 return; |
| 661 | 643 |
| 662 EnqueueOrder previous_fence = main_thread_only().current_fence; | 644 SequenceNumber previous_fence = main_thread_only().current_fence; |
| 663 main_thread_only().current_fence = 0; | 645 main_thread_only().current_fence = 0; |
| 664 | 646 |
| 665 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); | 647 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); |
| 666 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); | 648 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); |
| 667 | 649 |
| 668 if (!task_unblocked && previous_fence) { | 650 if (!task_unblocked && previous_fence) { |
| 669 base::AutoLock lock(immediate_incoming_queue_lock_); | 651 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 670 if (!immediate_incoming_queue().empty() && | 652 if (!immediate_incoming_queue().empty() && |
| 671 immediate_incoming_queue().front().enqueue_order() > previous_fence) { | 653 immediate_incoming_queue().front().enqueue_order().sequence_num > |
| 654 previous_fence) { |
| 672 task_unblocked = true; | 655 task_unblocked = true; |
| 673 } | 656 } |
| 674 } | 657 } |
| 675 | 658 |
| 676 if (IsQueueEnabled() && task_unblocked) { | 659 if (IsQueueEnabled() && task_unblocked) { |
| 677 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 660 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 678 FROM_HERE); | 661 FROM_HERE); |
| 679 } | 662 } |
| 680 } | 663 } |
| 681 | 664 |
| 682 bool TaskQueueImpl::BlockedByFence() const { | 665 bool TaskQueueImpl::BlockedByFence() const { |
| 683 if (!main_thread_only().current_fence) | 666 if (!main_thread_only().current_fence) |
| 684 return false; | 667 return false; |
| 685 | 668 |
| 686 if (!main_thread_only().immediate_work_queue->BlockedByFence() || | 669 if (!main_thread_only().immediate_work_queue->BlockedByFence() || |
| 687 !main_thread_only().delayed_work_queue->BlockedByFence()) { | 670 !main_thread_only().delayed_work_queue->BlockedByFence()) { |
| 688 return false; | 671 return false; |
| 689 } | 672 } |
| 690 | 673 |
| 691 base::AutoLock lock(immediate_incoming_queue_lock_); | 674 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 692 if (immediate_incoming_queue().empty()) | 675 if (immediate_incoming_queue().empty()) |
| 693 return true; | 676 return true; |
| 694 | 677 |
| 695 return immediate_incoming_queue().front().enqueue_order() > | 678 return immediate_incoming_queue().front().enqueue_order().sequence_num > |
| 696 main_thread_only().current_fence; | 679 main_thread_only().current_fence; |
| 697 } | 680 } |
| 698 | 681 |
| 699 bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const { | 682 bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const { |
| 700 if (!IsQueueEnabled()) | 683 if (!IsQueueEnabled()) |
| 701 return false; | 684 return false; |
| 702 | 685 |
| 703 if (!main_thread_only().current_fence) | 686 if (!main_thread_only().current_fence) |
| 704 return true; | 687 return true; |
| 705 | 688 |
| 706 return enqueue_order < main_thread_only().current_fence; | 689 return enqueue_order.sequence_num < main_thread_only().current_fence; |
| 707 } | 690 } |
| 708 | 691 |
| 709 EnqueueOrder TaskQueueImpl::GetFenceForTest() const { | 692 SequenceNumber TaskQueueImpl::GetFenceForTest() const { |
| 710 return main_thread_only().current_fence; | 693 return main_thread_only().current_fence; |
| 711 } | 694 } |
| 712 | 695 |
| 713 // static | 696 // static |
| 714 void TaskQueueImpl::QueueAsValueInto(const WTF::Deque<Task>& queue, | 697 void TaskQueueImpl::QueueAsValueInto(const WTF::Deque<Task>& queue, |
| 715 base::trace_event::TracedValue* state) { | 698 base::trace_event::TracedValue* state) { |
| 716 for (const Task& task : queue) { | 699 for (const Task& task : queue) { |
| 717 TaskAsValueInto(task, state); | 700 TaskAsValueInto(task, state); |
| 718 } | 701 } |
| 719 } | 702 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 732 mutable_queue->pop(); | 715 mutable_queue->pop(); |
| 733 } | 716 } |
| 734 *mutable_queue = std::move(visited); | 717 *mutable_queue = std::move(visited); |
| 735 } | 718 } |
| 736 | 719 |
| 737 // static | 720 // static |
| 738 void TaskQueueImpl::TaskAsValueInto(const Task& task, | 721 void TaskQueueImpl::TaskAsValueInto(const Task& task, |
| 739 base::trace_event::TracedValue* state) { | 722 base::trace_event::TracedValue* state) { |
| 740 state->BeginDictionary(); | 723 state->BeginDictionary(); |
| 741 state->SetString("posted_from", task.posted_from.ToString()); | 724 state->SetString("posted_from", task.posted_from.ToString()); |
| 742 #ifndef NDEBUG | 725 state->SetInteger("enqueue_order.delayed_run_time", |
| 743 if (task.enqueue_order_set()) | 726 task.enqueue_order().delayed_run_time.ToInternalValue()); |
| 744 state->SetInteger("enqueue_order", task.enqueue_order()); | 727 state->SetInteger("enqueue_order.sequence_num", |
| 745 #else | 728 task.enqueue_order().sequence_num); |
| 746 state->SetInteger("enqueue_order", task.enqueue_order()); | |
| 747 #endif | |
| 748 state->SetInteger("sequence_num", task.sequence_num); | 729 state->SetInteger("sequence_num", task.sequence_num); |
| 749 state->SetBoolean("nestable", task.nestable); | 730 state->SetBoolean("nestable", task.nestable); |
| 750 state->SetBoolean("is_high_res", task.is_high_res); | 731 state->SetBoolean("is_high_res", task.is_high_res); |
| 751 state->SetBoolean("is_cancelled", task.task.IsCancelled()); | 732 state->SetBoolean("is_cancelled", task.task.IsCancelled()); |
| 752 state->SetDouble( | 733 state->SetDouble( |
| 753 "delayed_run_time", | 734 "delayed_run_time", |
| 754 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 735 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
| 755 state->EndDictionary(); | 736 state->EndDictionary(); |
| 756 } | 737 } |
| 757 | 738 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 } | 884 } |
| 904 | 885 |
| 905 void TaskQueueImpl::NotifyWakeUpChangedOnMainThread(base::TimeTicks wake_up) { | 886 void TaskQueueImpl::NotifyWakeUpChangedOnMainThread(base::TimeTicks wake_up) { |
| 906 if (main_thread_only().observer) | 887 if (main_thread_only().observer) |
| 907 main_thread_only().observer->OnQueueNextWakeUpChanged(this, wake_up); | 888 main_thread_only().observer->OnQueueNextWakeUpChanged(this, wake_up); |
| 908 } | 889 } |
| 909 | 890 |
| 910 } // namespace internal | 891 } // namespace internal |
| 911 } // namespace scheduler | 892 } // namespace scheduler |
| 912 } // namespace blink | 893 } // namespace blink |
| OLD | NEW |