| 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" |
| 11 #include "platform/scheduler/base/work_queue.h" | 11 #include "platform/scheduler/base/work_queue.h" |
| 12 | 12 |
| 13 namespace blink { | 13 namespace blink { |
| 14 namespace scheduler { | 14 namespace scheduler { |
| 15 | 15 |
| 16 TaskQueue::TaskHandle::TaskHandle() : enqueue_order_(0), sequence_number_(0) {} |
| 17 |
| 18 TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue, uint64_t enqueue_order) |
| 19 : enqueue_order_(enqueue_order), |
| 20 #if DCHECK_IS_ON() |
| 21 task_queue_(task_queue), |
| 22 #endif |
| 23 sequence_number_(0) { |
| 24 DCHECK_GT(enqueue_order, 0ull); |
| 25 } |
| 26 |
| 27 TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue, |
| 28 base::TimeTicks scheduled_run_time, |
| 29 int sequence_number) |
| 30 : enqueue_order_(0), |
| 31 scheduled_run_time_(scheduled_run_time), |
| 32 #if DCHECK_IS_ON() |
| 33 task_queue_(task_queue), |
| 34 #endif |
| 35 sequence_number_(sequence_number) { |
| 36 DCHECK(!scheduled_run_time.is_null()); |
| 37 } |
| 38 |
| 39 TaskQueue::TaskHandle::operator bool() const { |
| 40 return !scheduled_run_time_.is_null() || |
| 41 internal::EnqueueOrderGenerator::IsValidEnqueueOrder(enqueue_order_); |
| 42 } |
| 43 |
| 16 namespace internal { | 44 namespace internal { |
| 17 | 45 |
| 18 TaskQueueImpl::TaskQueueImpl( | 46 TaskQueueImpl::TaskQueueImpl( |
| 19 TaskQueueManager* task_queue_manager, | 47 TaskQueueManager* task_queue_manager, |
| 20 TimeDomain* time_domain, | 48 TimeDomain* time_domain, |
| 21 const Spec& spec, | 49 const Spec& spec, |
| 22 const char* disabled_by_default_tracing_category, | 50 const char* disabled_by_default_tracing_category, |
| 23 const char* disabled_by_default_verbose_tracing_category) | 51 const char* disabled_by_default_verbose_tracing_category) |
| 24 : thread_id_(base::PlatformThread::CurrentId()), | 52 : thread_id_(base::PlatformThread::CurrentId()), |
| 25 any_thread_(task_queue_manager, time_domain), | 53 any_thread_(task_queue_manager, time_domain), |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 bool nestable, | 109 bool nestable, |
| 82 EnqueueOrder enqueue_order) | 110 EnqueueOrder enqueue_order) |
| 83 : PendingTask(posted_from, task, desired_run_time, nestable), | 111 : PendingTask(posted_from, task, desired_run_time, nestable), |
| 84 #ifndef NDEBUG | 112 #ifndef NDEBUG |
| 85 enqueue_order_set_(true), | 113 enqueue_order_set_(true), |
| 86 #endif | 114 #endif |
| 87 enqueue_order_(enqueue_order) { | 115 enqueue_order_(enqueue_order) { |
| 88 sequence_num = sequence_number; | 116 sequence_num = sequence_number; |
| 89 } | 117 } |
| 90 | 118 |
| 119 // static |
| 120 TaskQueueImpl::Task TaskQueueImpl::Task::CreateFakeTaskFromHandle( |
| 121 const TaskHandle& handle) { |
| 122 if (handle.scheduled_run_time_.is_null()) { |
| 123 // It's an immediate task. |
| 124 return Task(tracked_objects::Location(), base::Closure(), |
| 125 handle.scheduled_run_time_, handle.sequence_number_, false, |
| 126 handle.enqueue_order_); |
| 127 } else { |
| 128 // It's a delayed task. |
| 129 DCHECK_EQ(0ull, handle.enqueue_order_); |
| 130 return Task(tracked_objects::Location(), base::Closure(), |
| 131 handle.scheduled_run_time_, handle.sequence_number_, false); |
| 132 } |
| 133 } |
| 134 |
| 135 bool TaskQueueImpl::Task::DelayedRunTimeComparator::operator()( |
| 136 const Task& a, |
| 137 const Task& b) const { |
| 138 if (a.delayed_run_time < b.delayed_run_time) |
| 139 return true; |
| 140 |
| 141 if (a.delayed_run_time > b.delayed_run_time) |
| 142 return false; |
| 143 |
| 144 // If the times happen to match, then we use the sequence number to decide. |
| 145 // Compare the difference to support integer roll-over. |
| 146 return (a.sequence_num - b.sequence_num) < 0; |
| 147 } |
| 148 |
| 149 // static |
| 150 bool TaskQueueImpl::Task::EnqueueOrderComparatorFn(const Task& a, |
| 151 const Task& b) { |
| 152 return a.enqueue_order() < b.enqueue_order(); |
| 153 } |
| 154 |
| 155 // static |
| 156 bool TaskQueueImpl::Task::DelayedRunTimeComparatorFn(const Task& a, |
| 157 const Task& b) { |
| 158 if (a.delayed_run_time < b.delayed_run_time) |
| 159 return true; |
| 160 |
| 161 if (a.delayed_run_time > b.delayed_run_time) |
| 162 return false; |
| 163 |
| 164 // If the times happen to match, then we use the sequence number to decide. |
| 165 // Compare the difference to support integer roll-over. |
| 166 return (a.sequence_num - b.sequence_num) < 0; |
| 167 } |
| 168 |
| 91 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, | 169 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
| 92 TimeDomain* time_domain) | 170 TimeDomain* time_domain) |
| 93 : task_queue_manager(task_queue_manager), time_domain(time_domain) {} | 171 : task_queue_manager(task_queue_manager), |
| 172 time_domain(time_domain), |
| 173 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) { |
| 174 } |
| 94 | 175 |
| 95 TaskQueueImpl::AnyThread::~AnyThread() {} | 176 TaskQueueImpl::AnyThread::~AnyThread() {} |
| 96 | 177 |
| 97 TaskQueueImpl::MainThreadOnly::MainThreadOnly( | 178 TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
| 98 TaskQueueManager* task_queue_manager, | 179 TaskQueueManager* task_queue_manager, |
| 99 TaskQueueImpl* task_queue, | 180 TaskQueueImpl* task_queue, |
| 100 TimeDomain* time_domain) | 181 TimeDomain* time_domain) |
| 101 : task_queue_manager(task_queue_manager), | 182 : task_queue_manager(task_queue_manager), |
| 102 time_domain(time_domain), | 183 time_domain(time_domain), |
| 103 delayed_work_queue(new WorkQueue(task_queue, "delayed")), | 184 delayed_work_queue( |
| 104 immediate_work_queue(new WorkQueue(task_queue, "immediate")), | 185 new WorkQueue(task_queue, |
| 186 "delayed", |
| 187 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)), |
| 188 immediate_work_queue( |
| 189 new WorkQueue(task_queue, |
| 190 "immediate", |
| 191 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)), |
| 105 set_index(0), | 192 set_index(0), |
| 106 is_enabled(true), | 193 is_enabled(true), |
| 107 blame_context(nullptr), | 194 blame_context(nullptr), |
| 108 current_fence(0) {} | 195 current_fence(0) {} |
| 109 | 196 |
| 110 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 197 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
| 111 | 198 |
| 112 void TaskQueueImpl::UnregisterTaskQueue() { | 199 void TaskQueueImpl::UnregisterTaskQueue() { |
| 113 base::AutoLock lock(any_thread_lock_); | 200 base::AutoLock lock(any_thread_lock_); |
| 114 if (main_thread_only().time_domain) | 201 if (main_thread_only().time_domain) |
| 115 main_thread_only().time_domain->UnregisterQueue(this); | 202 main_thread_only().time_domain->UnregisterQueue(this); |
| 116 if (!any_thread().task_queue_manager) | 203 if (!any_thread().task_queue_manager) |
| 117 return; | 204 return; |
| 118 any_thread().time_domain = nullptr; | 205 any_thread().time_domain = nullptr; |
| 119 main_thread_only().time_domain = nullptr; | 206 main_thread_only().time_domain = nullptr; |
| 120 any_thread().task_queue_manager->UnregisterTaskQueue(this); | 207 any_thread().task_queue_manager->UnregisterTaskQueue(this); |
| 121 | 208 |
| 122 any_thread().task_queue_manager = nullptr; | 209 any_thread().task_queue_manager = nullptr; |
| 123 main_thread_only().task_queue_manager = nullptr; | 210 main_thread_only().task_queue_manager = nullptr; |
| 124 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); | 211 main_thread_only().delayed_incoming_queue.clear(); |
| 125 any_thread().immediate_incoming_queue = std::queue<Task>(); | 212 any_thread().immediate_incoming_queue.clear(); |
| 126 main_thread_only().immediate_work_queue.reset(); | 213 main_thread_only().immediate_work_queue.reset(); |
| 127 main_thread_only().delayed_work_queue.reset(); | 214 main_thread_only().delayed_work_queue.reset(); |
| 128 } | 215 } |
| 129 | 216 |
| 130 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { | 217 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { |
| 131 base::AutoLock lock(any_thread_lock_); | 218 base::AutoLock lock(any_thread_lock_); |
| 132 return base::PlatformThread::CurrentId() == thread_id_; | 219 return base::PlatformThread::CurrentId() == thread_id_; |
| 133 } | 220 } |
| 134 | 221 |
| 222 TaskQueue::TaskHandle TaskQueueImpl::PostCancellableDelayedTask( |
| 223 const tracked_objects::Location& from_here, |
| 224 const base::Closure& task, |
| 225 base::TimeDelta delay) { |
| 226 if (!main_thread_only().task_queue_manager) |
| 227 return TaskHandle(); |
| 228 |
| 229 EnqueueOrder sequence_number = |
| 230 main_thread_only().task_queue_manager->GetNextSequenceNumber(); |
| 231 |
| 232 if (delay.is_zero()) { |
| 233 base::AutoLock lock(any_thread_lock_); |
| 234 PushOntoImmediateIncomingQueueLocked( |
| 235 Task(from_here, task, base::TimeTicks(), sequence_number, true, |
| 236 sequence_number)); |
| 237 |
| 238 return TaskHandle(this, sequence_number); |
| 239 } else { |
| 240 DCHECK_GT(delay, base::TimeDelta()); |
| 241 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); |
| 242 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; |
| 243 PushOntoDelayedIncomingQueueFromMainThread( |
| 244 Task(from_here, task, time_domain_delayed_run_time, sequence_number, |
| 245 true), |
| 246 time_domain_now); |
| 247 |
| 248 return TaskHandle(this, time_domain_delayed_run_time, sequence_number); |
| 249 } |
| 250 } |
| 251 |
| 252 bool TaskQueueImpl::CancelTask(const TaskQueue::TaskHandle& handle) { |
| 253 if (!handle) |
| 254 return false; |
| 255 |
| 256 // If the TaskQueueManager has gone away, pretend we have canceled the task |
| 257 // because this simplifies logic in TimerBase::stop. |
| 258 if (!main_thread_only().task_queue_manager) |
| 259 return true; |
| 260 |
| 261 #if DCHECK_IS_ON() |
| 262 DCHECK_EQ(handle.task_queue_, this); |
| 263 #endif |
| 264 |
| 265 Task fake_task = Task::CreateFakeTaskFromHandle(handle); |
| 266 if (handle.scheduled_run_time_.is_null()) { |
| 267 // It's an immediate task. |
| 268 if (main_thread_only().immediate_work_queue->CancelTask(fake_task)) |
| 269 return true; |
| 270 |
| 271 base::AutoLock lock(any_thread_lock_); |
| 272 return any_thread().immediate_incoming_queue.erase(fake_task) > 0; |
| 273 } else { |
| 274 // It's a delayed task. |
| 275 DelayedRunTimeQueue::iterator it = |
| 276 main_thread_only().delayed_incoming_queue.find(fake_task); |
| 277 if (it != main_thread_only().delayed_incoming_queue.end()) { |
| 278 // It's safe to remove the wakeup from the TimeDomain only if this task's |
| 279 // scheduled run time was unique within the queue. |
| 280 bool can_cancel_timedomain_wakeup = true; |
| 281 if (it != main_thread_only().delayed_incoming_queue.begin()) { |
| 282 DelayedRunTimeQueue::iterator before = it; |
| 283 before--; |
| 284 if (before->delayed_run_time == handle.scheduled_run_time_) |
| 285 can_cancel_timedomain_wakeup = false; |
| 286 } |
| 287 if (can_cancel_timedomain_wakeup) { |
| 288 DelayedRunTimeQueue::iterator after = it; |
| 289 after++; |
| 290 if (after != main_thread_only().delayed_incoming_queue.end() && |
| 291 after->delayed_run_time == handle.scheduled_run_time_) { |
| 292 can_cancel_timedomain_wakeup = false; |
| 293 } |
| 294 } |
| 295 if (can_cancel_timedomain_wakeup) { |
| 296 main_thread_only().time_domain->CancelDelayedWork( |
| 297 this, handle.scheduled_run_time_); |
| 298 } |
| 299 |
| 300 main_thread_only().delayed_incoming_queue.erase(it); |
| 301 return true; |
| 302 } |
| 303 |
| 304 return main_thread_only().delayed_work_queue->CancelTask(fake_task); |
| 305 } |
| 306 } |
| 307 |
| 308 bool TaskQueueImpl::IsTaskPending(const TaskQueue::TaskHandle& handle) const { |
| 309 if (!handle) |
| 310 return false; |
| 311 |
| 312 // If the TaskQueueManager has gone away the task got cancelled. |
| 313 if (!main_thread_only().task_queue_manager) |
| 314 return false; |
| 315 |
| 316 #if DCHECK_IS_ON() |
| 317 DCHECK_EQ(handle.task_queue_, this); |
| 318 #endif |
| 319 |
| 320 Task fake_task = Task::CreateFakeTaskFromHandle(handle); |
| 321 if (handle.scheduled_run_time_.is_null()) { |
| 322 // It's an immediate task. |
| 323 if (main_thread_only().immediate_work_queue->IsTaskPending(fake_task)) |
| 324 return true; |
| 325 |
| 326 base::AutoLock lock(any_thread_lock_); |
| 327 return any_thread().immediate_incoming_queue.find(fake_task) != |
| 328 any_thread().immediate_incoming_queue.end(); |
| 329 } else { |
| 330 // It's a delayed task. |
| 331 DelayedRunTimeQueue::iterator it = |
| 332 main_thread_only().delayed_incoming_queue.find(fake_task); |
| 333 if (it != main_thread_only().delayed_incoming_queue.end()) |
| 334 return true; |
| 335 |
| 336 return main_thread_only().delayed_work_queue->IsTaskPending(fake_task); |
| 337 } |
| 338 } |
| 135 | 339 |
| 136 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, | 340 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, |
| 137 const base::Closure& task, | 341 const base::Closure& task, |
| 138 base::TimeDelta delay) { | 342 base::TimeDelta delay) { |
| 139 if (delay.is_zero()) | 343 if (delay.is_zero()) |
| 140 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); | 344 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); |
| 141 | 345 |
| 142 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); | 346 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); |
| 143 } | 347 } |
| 144 | 348 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 157 const base::Closure& task, | 361 const base::Closure& task, |
| 158 TaskType task_type) { | 362 TaskType task_type) { |
| 159 base::AutoLock lock(any_thread_lock_); | 363 base::AutoLock lock(any_thread_lock_); |
| 160 if (!any_thread().task_queue_manager) | 364 if (!any_thread().task_queue_manager) |
| 161 return false; | 365 return false; |
| 162 | 366 |
| 163 EnqueueOrder sequence_number = | 367 EnqueueOrder sequence_number = |
| 164 any_thread().task_queue_manager->GetNextSequenceNumber(); | 368 any_thread().task_queue_manager->GetNextSequenceNumber(); |
| 165 | 369 |
| 166 PushOntoImmediateIncomingQueueLocked( | 370 PushOntoImmediateIncomingQueueLocked( |
| 167 from_here, | 371 Task(from_here, task, base::TimeTicks(), sequence_number, |
| 168 task, | 372 task_type != TaskType::NON_NESTABLE, sequence_number)); |
| 169 base::TimeTicks(), | |
| 170 sequence_number, | |
| 171 task_type != TaskType::NON_NESTABLE); | |
| 172 return true; | 373 return true; |
| 173 } | 374 } |
| 174 | 375 |
| 175 bool TaskQueueImpl::PostDelayedTaskImpl( | 376 bool TaskQueueImpl::PostDelayedTaskImpl( |
| 176 const tracked_objects::Location& from_here, | 377 const tracked_objects::Location& from_here, |
| 177 const base::Closure& task, | 378 const base::Closure& task, |
| 178 base::TimeDelta delay, | 379 base::TimeDelta delay, |
| 179 TaskType task_type) { | 380 TaskType task_type) { |
| 180 DCHECK_GT(delay, base::TimeDelta()); | 381 DCHECK_GT(delay, base::TimeDelta()); |
| 181 if (base::PlatformThread::CurrentId() == thread_id_) { | 382 if (base::PlatformThread::CurrentId() == thread_id_) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 207 base::TimeTicks time_domain_now = any_thread().time_domain->Now(); | 408 base::TimeTicks time_domain_now = any_thread().time_domain->Now(); |
| 208 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; | 409 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; |
| 209 PushOntoDelayedIncomingQueueLocked( | 410 PushOntoDelayedIncomingQueueLocked( |
| 210 Task(from_here, task, time_domain_delayed_run_time, sequence_number, | 411 Task(from_here, task, time_domain_delayed_run_time, sequence_number, |
| 211 task_type != TaskType::NON_NESTABLE)); | 412 task_type != TaskType::NON_NESTABLE)); |
| 212 } | 413 } |
| 213 return true; | 414 return true; |
| 214 } | 415 } |
| 215 | 416 |
| 216 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( | 417 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( |
| 217 Task pending_task, base::TimeTicks now) { | 418 Task pending_task, |
| 419 base::TimeTicks now) { |
| 218 main_thread_only().task_queue_manager->DidQueueTask(pending_task); | 420 main_thread_only().task_queue_manager->DidQueueTask(pending_task); |
| 219 | 421 |
| 220 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. | 422 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. |
| 221 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 423 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; |
| 222 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 424 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); |
| 223 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, | 425 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, |
| 224 now); | 426 now); |
| 225 TraceQueueSize(false); | 427 TraceQueueSize(false); |
| 226 } | 428 } |
| 227 | 429 |
| 228 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { | 430 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { |
| 229 any_thread().task_queue_manager->DidQueueTask(pending_task); | 431 any_thread().task_queue_manager->DidQueueTask(pending_task); |
| 230 | 432 |
| 231 int thread_hop_task_sequence_number = | 433 int thread_hop_task_sequence_number = |
| 232 any_thread().task_queue_manager->GetNextSequenceNumber(); | 434 any_thread().task_queue_manager->GetNextSequenceNumber(); |
| 233 PushOntoImmediateIncomingQueueLocked( | 435 PushOntoImmediateIncomingQueueLocked( |
| 234 FROM_HERE, | 436 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
| 235 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 437 base::Passed(&pending_task)), |
| 236 base::Passed(&pending_task)), | 438 base::TimeTicks(), thread_hop_task_sequence_number, false, |
| 237 base::TimeTicks(), | 439 thread_hop_task_sequence_number)); |
| 238 thread_hop_task_sequence_number, | |
| 239 false); | |
| 240 } | 440 } |
| 241 | 441 |
| 242 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( | 442 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { |
| 243 const tracked_objects::Location& posted_from, | |
| 244 const base::Closure& task, | |
| 245 base::TimeTicks desired_run_time, | |
| 246 EnqueueOrder sequence_number, | |
| 247 bool nestable) { | |
| 248 if (any_thread().immediate_incoming_queue.empty()) | 443 if (any_thread().immediate_incoming_queue.empty()) |
| 249 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 444 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |
| 250 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make | 445 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |
| 251 // it run. | 446 // it run. |
| 252 if (any_thread().immediate_incoming_queue.empty()) { | 447 if (any_thread().immediate_incoming_queue.empty()) { |
| 253 // There's no point posting a DoWork for a disabled queue, however we can | 448 // 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. | 449 // only tell if it's disabled from the main thread. |
| 255 if (base::PlatformThread::CurrentId() == thread_id_) { | 450 if (base::PlatformThread::CurrentId() == thread_id_) { |
| 256 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) | 451 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) |
| 257 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 452 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 258 } else { | 453 } else { |
| 259 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 260 } | 455 } |
| 261 } | 456 } |
| 262 any_thread().immediate_incoming_queue.emplace( | 457 any_thread().task_queue_manager->DidQueueTask(pending_task); |
| 263 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n
umber); | 458 // We expect |pending_task| to be inserted at the end. Amoritized O(1). |
| 264 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming
_queue.back()); | 459 any_thread().immediate_incoming_queue.insert( |
| 460 any_thread().immediate_incoming_queue.end(), |
| 461 std::move(pending_task)); |
| 462 DCHECK_EQ(pending_task.enqueue_order(), |
| 463 any_thread().immediate_incoming_queue.rbegin()->enqueue_order()); |
| 265 TraceQueueSize(true); | 464 TraceQueueSize(true); |
| 266 } | 465 } |
| 267 | 466 |
| 268 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { | 467 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { |
| 269 DCHECK(main_thread_checker_.CalledOnValidThread()); | 468 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 270 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 469 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; |
| 271 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); | 470 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); |
| 272 // Make sure |delayed_run_time| isn't in the past. | 471 // Make sure |delayed_run_time| isn't in the past. |
| 273 if (delayed_run_time < time_domain_now) { | 472 if (delayed_run_time < time_domain_now) { |
| 274 delayed_run_time = time_domain_now; | 473 delayed_run_time = time_domain_now; |
| 275 pending_task.delayed_run_time = time_domain_now; | 474 pending_task.delayed_run_time = time_domain_now; |
| 276 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 475 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); |
| 277 LazyNow lazy_now(time_domain_now); | 476 LazyNow lazy_now(time_domain_now); |
| 278 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now); | 477 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now); |
| 279 } else { | 478 } else { |
| 280 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 479 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); |
| 281 main_thread_only().time_domain->ScheduleDelayedWork( | 480 main_thread_only().time_domain->ScheduleDelayedWork( |
| 282 this, delayed_run_time, main_thread_only().time_domain->Now()); | 481 this, delayed_run_time, main_thread_only().time_domain->Now()); |
| 283 } | 482 } |
| 284 TraceQueueSize(false); | 483 TraceQueueSize(false); |
| 285 } | 484 } |
| 286 | 485 |
| 287 void TaskQueueImpl::SetQueueEnabled(bool enabled) { | 486 void TaskQueueImpl::SetQueueEnabled(bool enabled) { |
| 288 if (main_thread_only().is_enabled == enabled) | 487 if (main_thread_only().is_enabled == enabled) |
| 289 return; | 488 return; |
| 290 main_thread_only().is_enabled = enabled; | 489 main_thread_only().is_enabled = enabled; |
| 291 if (!main_thread_only().task_queue_manager) | 490 if (!main_thread_only().task_queue_manager) |
| 292 return; | 491 return; |
| 293 if (enabled) { | 492 if (enabled) { |
| 294 // Note it's the job of the selector to tell the TaskQueueManager if | 493 // Note it's the job of the selector to tell the TaskQueueManager if |
| 295 // a DoWork needs posting. | 494 // a DoWork needs posting. |
| 296 main_thread_only().task_queue_manager->selector_.EnableQueue(this); | 495 main_thread_only().task_queue_manager->selector_.EnableQueue(this); |
| 297 } else { | 496 } else { |
| 298 main_thread_only().task_queue_manager->selector_.DisableQueue(this); | 497 main_thread_only().task_queue_manager->selector_.DisableQueue(this); |
| 299 } | 498 } |
| 300 } | 499 } |
| 301 | 500 |
| 302 bool TaskQueueImpl::IsQueueEnabled() const { | 501 bool TaskQueueImpl::IsQueueEnabled() const { |
| 303 return main_thread_only().is_enabled; | 502 return main_thread_only().is_enabled; |
| 304 } | 503 } |
| 305 | 504 |
| 306 bool TaskQueueImpl::IsEmpty() const { | 505 bool TaskQueueImpl::IsEmpty() const { |
| 307 if (!main_thread_only().delayed_work_queue->Empty() || | 506 if (!main_thread_only().delayed_work_queue->Empty() || |
| 308 !main_thread_only().delayed_incoming_queue.empty() || | |
| 309 !main_thread_only().immediate_work_queue->Empty()) { | 507 !main_thread_only().immediate_work_queue->Empty()) { |
| 310 return false; | 508 return false; |
| 311 } | 509 } |
| 312 | 510 |
| 313 base::AutoLock lock(any_thread_lock_); | 511 base::AutoLock lock(any_thread_lock_); |
| 314 return any_thread().immediate_incoming_queue.empty(); | 512 return any_thread().immediate_incoming_queue.empty() && |
| 513 main_thread_only().delayed_incoming_queue.empty(); |
| 315 } | 514 } |
| 316 | 515 |
| 317 bool TaskQueueImpl::HasPendingImmediateWork() const { | 516 bool TaskQueueImpl::HasPendingImmediateWork() const { |
| 318 // Any work queue tasks count as immediate work. | 517 // Any work queue tasks count as immediate work. |
| 319 if (!main_thread_only().delayed_work_queue->Empty() || | 518 if (!main_thread_only().delayed_work_queue->Empty() || |
| 320 !main_thread_only().immediate_work_queue->Empty()) { | 519 !main_thread_only().immediate_work_queue->Empty()) { |
| 321 return true; | 520 return true; |
| 322 } | 521 } |
| 323 | 522 |
| 324 // Tasks on |delayed_incoming_queue| that could run now, count as | 523 // Tasks on |delayed_incoming_queue| that could run now, count as |
| 325 // immediate work. | 524 // immediate work. |
| 326 if (!main_thread_only().delayed_incoming_queue.empty() && | 525 if (!main_thread_only().delayed_incoming_queue.empty() && |
| 327 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 526 main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= |
| 328 main_thread_only().time_domain->CreateLazyNow().Now()) { | 527 main_thread_only().time_domain->CreateLazyNow().Now()) { |
| 329 return true; | 528 return true; |
| 330 } | 529 } |
| 331 | 530 |
| 332 // Finally tasks on |immediate_incoming_queue| count as immediate work. | 531 // Finally tasks on |immediate_incoming_queue| count as immediate work. |
| 333 base::AutoLock lock(any_thread_lock_); | 532 base::AutoLock lock(any_thread_lock_); |
| 334 return !any_thread().immediate_incoming_queue.empty(); | 533 return !any_thread().immediate_incoming_queue.empty(); |
| 335 } | 534 } |
| 336 | 535 |
| 337 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { | 536 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { |
| 338 // Enqueue all delayed tasks that should be running now, skipping any that | 537 // Enqueue all delayed tasks that should be running now. |
| 339 // have been canceled. | |
| 340 while (!main_thread_only().delayed_incoming_queue.empty()) { | 538 while (!main_thread_only().delayed_incoming_queue.empty()) { |
| 539 DelayedRunTimeQueue::iterator next_task = |
| 540 main_thread_only().delayed_incoming_queue.begin(); |
| 541 if (next_task->delayed_run_time > lazy_now->Now()) |
| 542 break; |
| 341 // TODO(alexclarke): Use extract() when C++17 is allowed. | 543 // TODO(alexclarke): Use extract() when C++17 is allowed. |
| 342 Task& task = | 544 Task& task = const_cast<Task&>(*next_task); |
| 343 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); | |
| 344 if (task.task.IsCancelled()) { | |
| 345 main_thread_only().delayed_incoming_queue.pop(); | |
| 346 continue; | |
| 347 } | |
| 348 if (task.delayed_run_time > lazy_now->Now()) | |
| 349 break; | |
| 350 task.set_enqueue_order( | 545 task.set_enqueue_order( |
| 351 main_thread_only().task_queue_manager->GetNextSequenceNumber()); | 546 main_thread_only().task_queue_manager->GetNextSequenceNumber()); |
| 352 main_thread_only().delayed_work_queue->Push(std::move(task)); | 547 main_thread_only().delayed_work_queue->Push(std::move(task)); |
| 353 main_thread_only().delayed_incoming_queue.pop(); | 548 main_thread_only().delayed_incoming_queue.erase(next_task); |
| 354 } | 549 } |
| 355 } | 550 } |
| 356 | 551 |
| 357 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() { | 552 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now) { |
| 358 if (!main_thread_only().task_queue_manager) | 553 if (!main_thread_only().task_queue_manager) |
| 359 return false; | 554 return; |
| 555 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); |
| 556 TraceQueueSize(false); |
| 557 } |
| 360 | 558 |
| 361 if (!main_thread_only().immediate_work_queue->Empty()) | 559 void TaskQueueImpl::UpdateImmediateWorkQueue() { |
| 362 return true; | 560 DCHECK(main_thread_only().immediate_work_queue->Empty()); |
| 561 base::AutoLock lock(any_thread_lock_); |
| 562 if (!main_thread_only().task_queue_manager) |
| 563 return; |
| 363 | 564 |
| 364 base::AutoLock lock(any_thread_lock_); | |
| 365 main_thread_only().immediate_work_queue->SwapLocked( | 565 main_thread_only().immediate_work_queue->SwapLocked( |
| 366 any_thread().immediate_incoming_queue); | 566 any_thread().immediate_incoming_queue); |
| 367 // |immediate_work_queue| is now empty so updates are no longer required. | 567 |
| 368 return false; | 568 // |any_thread().immediate_incoming_queue| is now empty so |
| 569 // TimeDomain::UpdateQueues no longer needs to consider this queue for |
| 570 // reloading. |
| 571 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); |
| 369 } | 572 } |
| 370 | 573 |
| 371 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { | 574 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { |
| 372 bool is_tracing; | 575 bool is_tracing; |
| 373 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, | 576 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, |
| 374 &is_tracing); | 577 &is_tracing); |
| 375 if (!is_tracing) | 578 if (!is_tracing) |
| 376 return; | 579 return; |
| 377 | 580 |
| 378 // It's only safe to access the work queues from the main thread. | 581 // It's only safe to access the work queues from the main thread. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 state->SetInteger("immediate_incoming_queue_size", | 643 state->SetInteger("immediate_incoming_queue_size", |
| 441 any_thread().immediate_incoming_queue.size()); | 644 any_thread().immediate_incoming_queue.size()); |
| 442 state->SetInteger("delayed_incoming_queue_size", | 645 state->SetInteger("delayed_incoming_queue_size", |
| 443 main_thread_only().delayed_incoming_queue.size()); | 646 main_thread_only().delayed_incoming_queue.size()); |
| 444 state->SetInteger("immediate_work_queue_size", | 647 state->SetInteger("immediate_work_queue_size", |
| 445 main_thread_only().immediate_work_queue->Size()); | 648 main_thread_only().immediate_work_queue->Size()); |
| 446 state->SetInteger("delayed_work_queue_size", | 649 state->SetInteger("delayed_work_queue_size", |
| 447 main_thread_only().delayed_work_queue->Size()); | 650 main_thread_only().delayed_work_queue->Size()); |
| 448 if (!main_thread_only().delayed_incoming_queue.empty()) { | 651 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 449 base::TimeDelta delay_to_next_task = | 652 base::TimeDelta delay_to_next_task = |
| 450 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - | 653 (main_thread_only().delayed_incoming_queue.begin()->delayed_run_time - |
| 451 main_thread_only().time_domain->CreateLazyNow().Now()); | 654 main_thread_only().time_domain->CreateLazyNow().Now()); |
| 452 state->SetDouble("delay_to_next_task_ms", | 655 state->SetDouble("delay_to_next_task_ms", |
| 453 delay_to_next_task.InMillisecondsF()); | 656 delay_to_next_task.InMillisecondsF()); |
| 454 } | 657 } |
| 455 if (verbose_tracing_enabled) { | 658 if (verbose_tracing_enabled) { |
| 456 state->BeginArray("immediate_incoming_queue"); | 659 state->BeginArray("immediate_incoming_queue"); |
| 457 QueueAsValueInto(any_thread().immediate_incoming_queue, state); | 660 QueueAsValueInto(any_thread().immediate_incoming_queue, state); |
| 458 state->EndArray(); | 661 state->EndArray(); |
| 459 state->BeginArray("delayed_work_queue"); | 662 state->BeginArray("delayed_work_queue"); |
| 460 main_thread_only().delayed_work_queue->AsValueInto(state); | 663 main_thread_only().delayed_work_queue->AsValueInto(state); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 // Tasks posted after this point will have a strictly higher enqueue order | 746 // Tasks posted after this point will have a strictly higher enqueue order |
| 544 // and will be blocked from running. | 747 // and will be blocked from running. |
| 545 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( | 748 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( |
| 546 main_thread_only().current_fence); | 749 main_thread_only().current_fence); |
| 547 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( | 750 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( |
| 548 main_thread_only().current_fence); | 751 main_thread_only().current_fence); |
| 549 | 752 |
| 550 if (!task_unblocked && previous_fence) { | 753 if (!task_unblocked && previous_fence) { |
| 551 base::AutoLock lock(any_thread_lock_); | 754 base::AutoLock lock(any_thread_lock_); |
| 552 if (!any_thread().immediate_incoming_queue.empty() && | 755 if (!any_thread().immediate_incoming_queue.empty() && |
| 553 any_thread().immediate_incoming_queue.front().enqueue_order() > | 756 any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 554 previous_fence && | 757 previous_fence && |
| 555 any_thread().immediate_incoming_queue.front().enqueue_order() < | 758 any_thread().immediate_incoming_queue.begin()->enqueue_order() < |
| 556 main_thread_only().current_fence) { | 759 main_thread_only().current_fence) { |
| 557 task_unblocked = true; | 760 task_unblocked = true; |
| 558 } | 761 } |
| 559 } | 762 } |
| 560 | 763 |
| 561 if (main_thread_only().is_enabled && task_unblocked) { | 764 if (main_thread_only().is_enabled && task_unblocked) { |
| 562 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 765 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 563 FROM_HERE); | 766 FROM_HERE); |
| 564 } | 767 } |
| 565 } | 768 } |
| 566 | 769 |
| 567 void TaskQueueImpl::RemoveFence() { | 770 void TaskQueueImpl::RemoveFence() { |
| 568 if (!main_thread_only().task_queue_manager) | 771 if (!main_thread_only().task_queue_manager) |
| 569 return; | 772 return; |
| 570 | 773 |
| 571 EnqueueOrder previous_fence = main_thread_only().current_fence; | 774 EnqueueOrder previous_fence = main_thread_only().current_fence; |
| 572 main_thread_only().current_fence = 0; | 775 main_thread_only().current_fence = 0; |
| 573 | 776 |
| 574 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); | 777 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); |
| 575 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); | 778 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); |
| 576 | 779 |
| 577 if (!task_unblocked && previous_fence) { | 780 if (!task_unblocked && previous_fence) { |
| 578 base::AutoLock lock(any_thread_lock_); | 781 base::AutoLock lock(any_thread_lock_); |
| 579 if (!any_thread().immediate_incoming_queue.empty() && | 782 if (!any_thread().immediate_incoming_queue.empty() && |
| 580 any_thread().immediate_incoming_queue.front().enqueue_order() > | 783 any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 581 previous_fence) { | 784 previous_fence) { |
| 582 task_unblocked = true; | 785 task_unblocked = true; |
| 583 } | 786 } |
| 584 } | 787 } |
| 585 | 788 |
| 586 if (main_thread_only().is_enabled && task_unblocked) { | 789 if (main_thread_only().is_enabled && task_unblocked) { |
| 587 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 790 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 588 FROM_HERE); | 791 FROM_HERE); |
| 589 } | 792 } |
| 590 } | 793 } |
| 591 | 794 |
| 592 bool TaskQueueImpl::BlockedByFence() const { | 795 bool TaskQueueImpl::BlockedByFence() const { |
| 593 if (!main_thread_only().current_fence) | 796 if (!main_thread_only().current_fence) |
| 594 return false; | 797 return false; |
| 595 | 798 |
| 596 if (!main_thread_only().immediate_work_queue->BlockedByFence() || | 799 if (!main_thread_only().immediate_work_queue->BlockedByFence() || |
| 597 !main_thread_only().delayed_work_queue->BlockedByFence()) { | 800 !main_thread_only().delayed_work_queue->BlockedByFence()) { |
| 598 return false; | 801 return false; |
| 599 } | 802 } |
| 600 | 803 |
| 601 base::AutoLock lock(any_thread_lock_); | 804 base::AutoLock lock(any_thread_lock_); |
| 602 if (any_thread().immediate_incoming_queue.empty()) | 805 if (any_thread().immediate_incoming_queue.empty()) |
| 603 return true; | 806 return true; |
| 604 | 807 |
| 605 return any_thread().immediate_incoming_queue.front().enqueue_order() > | 808 return any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 606 main_thread_only().current_fence; | 809 main_thread_only().current_fence; |
| 607 } | 810 } |
| 608 | 811 |
| 609 bool TaskQueueImpl::BlockedByFenceLocked() const { | 812 bool TaskQueueImpl::BlockedByFenceLocked() const { |
| 610 if (!main_thread_only().current_fence) | 813 if (!main_thread_only().current_fence) |
| 611 return false; | 814 return false; |
| 612 | 815 |
| 613 if (!main_thread_only().immediate_work_queue->BlockedByFence() || | 816 if (!main_thread_only().immediate_work_queue->BlockedByFence() || |
| 614 !main_thread_only().delayed_work_queue->BlockedByFence()) { | 817 !main_thread_only().delayed_work_queue->BlockedByFence()) { |
| 615 return false; | 818 return false; |
| 616 } | 819 } |
| 617 | 820 |
| 618 if (any_thread().immediate_incoming_queue.empty()) | 821 if (any_thread().immediate_incoming_queue.empty()) |
| 619 return true; | 822 return true; |
| 620 | 823 |
| 621 return any_thread().immediate_incoming_queue.front().enqueue_order() > | 824 return any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 622 main_thread_only().current_fence; | 825 main_thread_only().current_fence; |
| 623 } | 826 } |
| 624 | 827 |
| 625 // static | 828 // static |
| 626 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, | 829 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, |
| 627 base::trace_event::TracedValue* state) { | 830 base::trace_event::TracedValue* state) { |
| 628 // Remove const to search |queue| in the destructive manner. Restore the | 831 for (const Task& task : queue) { |
| 629 // content from |visited| later. | 832 TaskAsValueInto(task, state); |
| 630 std::queue<Task>* mutable_queue = const_cast<std::queue<Task>*>(&queue); | |
| 631 std::queue<Task> visited; | |
| 632 while (!mutable_queue->empty()) { | |
| 633 TaskAsValueInto(mutable_queue->front(), state); | |
| 634 visited.push(std::move(mutable_queue->front())); | |
| 635 mutable_queue->pop(); | |
| 636 } | 833 } |
| 637 *mutable_queue = std::move(visited); | |
| 638 } | 834 } |
| 639 | 835 |
| 640 // static | 836 // static |
| 641 void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue, | 837 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, |
| 642 base::trace_event::TracedValue* state) { | 838 base::trace_event::TracedValue* state) { |
| 643 // Remove const to search |queue| in the destructive manner. Restore the | 839 for (const Task& task : queue) { |
| 644 // content from |visited| later. | 840 TaskAsValueInto(task, state); |
| 645 std::priority_queue<Task>* mutable_queue = | |
| 646 const_cast<std::priority_queue<Task>*>(&queue); | |
| 647 std::priority_queue<Task> visited; | |
| 648 while (!mutable_queue->empty()) { | |
| 649 TaskAsValueInto(mutable_queue->top(), state); | |
| 650 visited.push(std::move(const_cast<Task&>(mutable_queue->top()))); | |
| 651 mutable_queue->pop(); | |
| 652 } | 841 } |
| 653 *mutable_queue = std::move(visited); | |
| 654 } | 842 } |
| 655 | 843 |
| 656 // static | 844 // static |
| 657 void TaskQueueImpl::TaskAsValueInto(const Task& task, | 845 void TaskQueueImpl::TaskAsValueInto(const Task& task, |
| 658 base::trace_event::TracedValue* state) { | 846 base::trace_event::TracedValue* state) { |
| 659 state->BeginDictionary(); | 847 state->BeginDictionary(); |
| 660 state->SetString("posted_from", task.posted_from.ToString()); | 848 state->SetString("posted_from", task.posted_from.ToString()); |
| 661 #ifndef NDEBUG | 849 #ifndef NDEBUG |
| 662 if (task.enqueue_order_set()) | 850 if (task.enqueue_order_set()) |
| 663 state->SetInteger("enqueue_order", task.enqueue_order()); | 851 state->SetInteger("enqueue_order", task.enqueue_order()); |
| 664 #else | 852 #else |
| 665 state->SetInteger("enqueue_order", task.enqueue_order()); | 853 state->SetInteger("enqueue_order", task.enqueue_order()); |
| 666 #endif | 854 #endif |
| 667 state->SetInteger("sequence_num", task.sequence_num); | 855 state->SetInteger("sequence_num", task.sequence_num); |
| 668 state->SetBoolean("nestable", task.nestable); | 856 state->SetBoolean("nestable", task.nestable); |
| 669 state->SetBoolean("is_high_res", task.is_high_res); | 857 state->SetBoolean("is_high_res", task.is_high_res); |
| 670 state->SetBoolean("is_cancelled", task.task.IsCancelled()); | |
| 671 state->SetDouble( | 858 state->SetDouble( |
| 672 "delayed_run_time", | 859 "delayed_run_time", |
| 673 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 860 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
| 674 state->EndDictionary(); | 861 state->EndDictionary(); |
| 675 } | 862 } |
| 676 | 863 |
| 677 } // namespace internal | 864 } // namespace internal |
| 678 } // namespace scheduler | 865 } // namespace scheduler |
| 679 } // namespace blink | 866 } // namespace blink |
| OLD | NEW |