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