| Index: third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc | 
| diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc | 
| index 7a8da55f6de9817fac85eedcd6f3e781f0885529..1b0980a4f4e00ccf236f4bc2250683d0b744c3b7 100644 | 
| --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc | 
| +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc | 
| @@ -12,6 +12,34 @@ | 
|  | 
| namespace blink { | 
| namespace scheduler { | 
| + | 
| +TaskQueue::TaskHandle::TaskHandle() : enqueue_order_(0), sequence_number_(0) {} | 
| + | 
| +TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue, uint64_t enqueue_order) | 
| +    : enqueue_order_(enqueue_order), | 
| +#if DCHECK_IS_ON() | 
| +      task_queue_(task_queue), | 
| +#endif | 
| +      sequence_number_(0) { | 
| +  DCHECK_GT(enqueue_order, 0ull); | 
| +} | 
| + | 
| +TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue, | 
| +                                  base::TimeTicks scheduled_run_time, | 
| +                                  int sequence_number) | 
| +    : enqueue_order_(0), | 
| +      scheduled_run_time_(scheduled_run_time), | 
| +#if DCHECK_IS_ON() | 
| +      task_queue_(task_queue), | 
| +#endif | 
| +      sequence_number_(sequence_number) { | 
| +  DCHECK(!scheduled_run_time.is_null()); | 
| +} | 
| + | 
| +TaskQueue::TaskHandle::operator bool() const { | 
| +  return !scheduled_run_time_.is_null() || | 
| +         internal::EnqueueOrderGenerator::IsValidEnqueueOrder(enqueue_order_); | 
| +} | 
|  | 
| namespace internal { | 
|  | 
| @@ -88,9 +116,62 @@ | 
| sequence_num = sequence_number; | 
| } | 
|  | 
| +// static | 
| +TaskQueueImpl::Task TaskQueueImpl::Task::CreateFakeTaskFromHandle( | 
| +    const TaskHandle& handle) { | 
| +  if (handle.scheduled_run_time_.is_null()) { | 
| +    // It's an immediate task. | 
| +    return Task(tracked_objects::Location(), base::Closure(), | 
| +                handle.scheduled_run_time_, handle.sequence_number_, false, | 
| +                handle.enqueue_order_); | 
| +  } else { | 
| +    // It's a delayed task. | 
| +    DCHECK_EQ(0ull, handle.enqueue_order_); | 
| +    return Task(tracked_objects::Location(), base::Closure(), | 
| +                handle.scheduled_run_time_, handle.sequence_number_, false); | 
| +  } | 
| +} | 
| + | 
| +bool TaskQueueImpl::Task::DelayedRunTimeComparator::operator()( | 
| +    const Task& a, | 
| +    const Task& b) const { | 
| +  if (a.delayed_run_time < b.delayed_run_time) | 
| +    return true; | 
| + | 
| +  if (a.delayed_run_time > b.delayed_run_time) | 
| +    return false; | 
| + | 
| +  // If the times happen to match, then we use the sequence number to decide. | 
| +  // Compare the difference to support integer roll-over. | 
| +  return (a.sequence_num - b.sequence_num) < 0; | 
| +} | 
| + | 
| +// static | 
| +bool TaskQueueImpl::Task::EnqueueOrderComparatorFn(const Task& a, | 
| +                                                   const Task& b) { | 
| +  return a.enqueue_order() < b.enqueue_order(); | 
| +} | 
| + | 
| +// static | 
| +bool TaskQueueImpl::Task::DelayedRunTimeComparatorFn(const Task& a, | 
| +                                                     const Task& b) { | 
| +  if (a.delayed_run_time < b.delayed_run_time) | 
| +    return true; | 
| + | 
| +  if (a.delayed_run_time > b.delayed_run_time) | 
| +    return false; | 
| + | 
| +  // If the times happen to match, then we use the sequence number to decide. | 
| +  // Compare the difference to support integer roll-over. | 
| +  return (a.sequence_num - b.sequence_num) < 0; | 
| +} | 
| + | 
| TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, | 
| TimeDomain* time_domain) | 
| -    : task_queue_manager(task_queue_manager), time_domain(time_domain) {} | 
| +    : task_queue_manager(task_queue_manager), | 
| +      time_domain(time_domain), | 
| +      immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) { | 
| +} | 
|  | 
| TaskQueueImpl::AnyThread::~AnyThread() {} | 
|  | 
| @@ -100,8 +181,14 @@ | 
| TimeDomain* time_domain) | 
| : task_queue_manager(task_queue_manager), | 
| time_domain(time_domain), | 
| -      delayed_work_queue(new WorkQueue(task_queue, "delayed")), | 
| -      immediate_work_queue(new WorkQueue(task_queue, "immediate")), | 
| +      delayed_work_queue( | 
| +          new WorkQueue(task_queue, | 
| +                        "delayed", | 
| +                        &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)), | 
| +      immediate_work_queue( | 
| +          new WorkQueue(task_queue, | 
| +                        "immediate", | 
| +                        &TaskQueueImpl::Task::EnqueueOrderComparatorFn)), | 
| set_index(0), | 
| is_enabled(true), | 
| blame_context(nullptr), | 
| @@ -121,8 +208,8 @@ | 
|  | 
| any_thread().task_queue_manager = nullptr; | 
| main_thread_only().task_queue_manager = nullptr; | 
| -  main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); | 
| -  any_thread().immediate_incoming_queue = std::queue<Task>(); | 
| +  main_thread_only().delayed_incoming_queue.clear(); | 
| +  any_thread().immediate_incoming_queue.clear(); | 
| main_thread_only().immediate_work_queue.reset(); | 
| main_thread_only().delayed_work_queue.reset(); | 
| } | 
| @@ -132,6 +219,123 @@ | 
| return base::PlatformThread::CurrentId() == thread_id_; | 
| } | 
|  | 
| +TaskQueue::TaskHandle TaskQueueImpl::PostCancellableDelayedTask( | 
| +    const tracked_objects::Location& from_here, | 
| +    const base::Closure& task, | 
| +    base::TimeDelta delay) { | 
| +  if (!main_thread_only().task_queue_manager) | 
| +    return TaskHandle(); | 
| + | 
| +  EnqueueOrder sequence_number = | 
| +      main_thread_only().task_queue_manager->GetNextSequenceNumber(); | 
| + | 
| +  if (delay.is_zero()) { | 
| +    base::AutoLock lock(any_thread_lock_); | 
| +    PushOntoImmediateIncomingQueueLocked( | 
| +        Task(from_here, task, base::TimeTicks(), sequence_number, true, | 
| +             sequence_number)); | 
| + | 
| +    return TaskHandle(this, sequence_number); | 
| +  } else { | 
| +    DCHECK_GT(delay, base::TimeDelta()); | 
| +    base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); | 
| +    base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; | 
| +    PushOntoDelayedIncomingQueueFromMainThread( | 
| +        Task(from_here, task, time_domain_delayed_run_time, sequence_number, | 
| +             true), | 
| +        time_domain_now); | 
| + | 
| +    return TaskHandle(this, time_domain_delayed_run_time, sequence_number); | 
| +  } | 
| +} | 
| + | 
| +bool TaskQueueImpl::CancelTask(const TaskQueue::TaskHandle& handle) { | 
| +  if (!handle) | 
| +    return false; | 
| + | 
| +  // If the TaskQueueManager has gone away, pretend we have canceled the task | 
| +  // because this simplifies logic in TimerBase::stop. | 
| +  if (!main_thread_only().task_queue_manager) | 
| +    return true; | 
| + | 
| +#if DCHECK_IS_ON() | 
| +  DCHECK_EQ(handle.task_queue_, this); | 
| +#endif | 
| + | 
| +  Task fake_task = Task::CreateFakeTaskFromHandle(handle); | 
| +  if (handle.scheduled_run_time_.is_null()) { | 
| +    // It's an immediate task. | 
| +    if (main_thread_only().immediate_work_queue->CancelTask(fake_task)) | 
| +      return true; | 
| + | 
| +    base::AutoLock lock(any_thread_lock_); | 
| +    return any_thread().immediate_incoming_queue.erase(fake_task) > 0; | 
| +  } else { | 
| +    // It's a delayed task. | 
| +    DelayedRunTimeQueue::iterator it = | 
| +        main_thread_only().delayed_incoming_queue.find(fake_task); | 
| +    if (it != main_thread_only().delayed_incoming_queue.end()) { | 
| +      // It's safe to remove the wakeup from the TimeDomain only if this task's | 
| +      // scheduled run time was unique within the queue. | 
| +      bool can_cancel_timedomain_wakeup = true; | 
| +      if (it != main_thread_only().delayed_incoming_queue.begin()) { | 
| +        DelayedRunTimeQueue::iterator before = it; | 
| +        before--; | 
| +        if (before->delayed_run_time == handle.scheduled_run_time_) | 
| +          can_cancel_timedomain_wakeup = false; | 
| +      } | 
| +      if (can_cancel_timedomain_wakeup) { | 
| +        DelayedRunTimeQueue::iterator after = it; | 
| +        after++; | 
| +        if (after != main_thread_only().delayed_incoming_queue.end() && | 
| +            after->delayed_run_time == handle.scheduled_run_time_) { | 
| +          can_cancel_timedomain_wakeup = false; | 
| +        } | 
| +      } | 
| +      if (can_cancel_timedomain_wakeup) { | 
| +        main_thread_only().time_domain->CancelDelayedWork( | 
| +            this, handle.scheduled_run_time_); | 
| +      } | 
| + | 
| +      main_thread_only().delayed_incoming_queue.erase(it); | 
| +      return true; | 
| +    } | 
| + | 
| +    return main_thread_only().delayed_work_queue->CancelTask(fake_task); | 
| +  } | 
| +} | 
| + | 
| +bool TaskQueueImpl::IsTaskPending(const TaskQueue::TaskHandle& handle) const { | 
| +  if (!handle) | 
| +    return false; | 
| + | 
| +  // If the TaskQueueManager has gone away the task got cancelled. | 
| +  if (!main_thread_only().task_queue_manager) | 
| +    return false; | 
| + | 
| +#if DCHECK_IS_ON() | 
| +  DCHECK_EQ(handle.task_queue_, this); | 
| +#endif | 
| + | 
| +  Task fake_task = Task::CreateFakeTaskFromHandle(handle); | 
| +  if (handle.scheduled_run_time_.is_null()) { | 
| +    // It's an immediate task. | 
| +    if (main_thread_only().immediate_work_queue->IsTaskPending(fake_task)) | 
| +      return true; | 
| + | 
| +    base::AutoLock lock(any_thread_lock_); | 
| +    return any_thread().immediate_incoming_queue.find(fake_task) != | 
| +           any_thread().immediate_incoming_queue.end(); | 
| +  } else { | 
| +    // It's a delayed task. | 
| +    DelayedRunTimeQueue::iterator it = | 
| +        main_thread_only().delayed_incoming_queue.find(fake_task); | 
| +    if (it != main_thread_only().delayed_incoming_queue.end()) | 
| +      return true; | 
| + | 
| +    return main_thread_only().delayed_work_queue->IsTaskPending(fake_task); | 
| +  } | 
| +} | 
|  | 
| bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, | 
| const base::Closure& task, | 
| @@ -164,11 +368,8 @@ | 
| any_thread().task_queue_manager->GetNextSequenceNumber(); | 
|  | 
| PushOntoImmediateIncomingQueueLocked( | 
| -      from_here, | 
| -      task, | 
| -      base::TimeTicks(), | 
| -      sequence_number, | 
| -      task_type != TaskType::NON_NESTABLE); | 
| +      Task(from_here, task, base::TimeTicks(), sequence_number, | 
| +           task_type != TaskType::NON_NESTABLE, sequence_number)); | 
| return true; | 
| } | 
|  | 
| @@ -214,12 +415,13 @@ | 
| } | 
|  | 
| void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( | 
| -    Task pending_task, base::TimeTicks now) { | 
| +    Task pending_task, | 
| +    base::TimeTicks now) { | 
| main_thread_only().task_queue_manager->DidQueueTask(pending_task); | 
|  | 
| // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. | 
| base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 
| -  main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 
| +  main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); | 
| main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, | 
| now); | 
| TraceQueueSize(false); | 
| @@ -231,20 +433,13 @@ | 
| int thread_hop_task_sequence_number = | 
| any_thread().task_queue_manager->GetNextSequenceNumber(); | 
| PushOntoImmediateIncomingQueueLocked( | 
| -     FROM_HERE, | 
| -     base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 
| -                base::Passed(&pending_task)), | 
| -     base::TimeTicks(), | 
| -     thread_hop_task_sequence_number, | 
| -     false); | 
| -} | 
| - | 
| -void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( | 
| -         const tracked_objects::Location& posted_from, | 
| -         const base::Closure& task, | 
| -         base::TimeTicks desired_run_time, | 
| -         EnqueueOrder sequence_number, | 
| -         bool nestable) { | 
| +      Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 
| +                                 base::Passed(&pending_task)), | 
| +           base::TimeTicks(), thread_hop_task_sequence_number, false, | 
| +           thread_hop_task_sequence_number)); | 
| +} | 
| + | 
| +void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { | 
| if (any_thread().immediate_incoming_queue.empty()) | 
| any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 
| // If the |immediate_incoming_queue| is empty we need a DoWork posted to make | 
| @@ -259,9 +454,13 @@ | 
| any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 
| } | 
| } | 
| -  any_thread().immediate_incoming_queue.emplace( | 
| -      posted_from, task, desired_run_time, sequence_number, nestable, sequence_number); | 
| -  any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming_queue.back()); | 
| +  any_thread().task_queue_manager->DidQueueTask(pending_task); | 
| +  // We expect |pending_task| to be inserted at the end. Amoritized O(1). | 
| +  any_thread().immediate_incoming_queue.insert( | 
| +      any_thread().immediate_incoming_queue.end(), | 
| +      std::move(pending_task)); | 
| +  DCHECK_EQ(pending_task.enqueue_order(), | 
| +            any_thread().immediate_incoming_queue.rbegin()->enqueue_order()); | 
| TraceQueueSize(true); | 
| } | 
|  | 
| @@ -273,11 +472,11 @@ | 
| if (delayed_run_time < time_domain_now) { | 
| delayed_run_time = time_domain_now; | 
| pending_task.delayed_run_time = time_domain_now; | 
| -    main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 
| +    main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); | 
| LazyNow lazy_now(time_domain_now); | 
| MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now); | 
| } else { | 
| -    main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 
| +    main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); | 
| main_thread_only().time_domain->ScheduleDelayedWork( | 
| this, delayed_run_time, main_thread_only().time_domain->Now()); | 
| } | 
| @@ -305,13 +504,13 @@ | 
|  | 
| bool TaskQueueImpl::IsEmpty() const { | 
| if (!main_thread_only().delayed_work_queue->Empty() || | 
| -      !main_thread_only().delayed_incoming_queue.empty() || | 
| !main_thread_only().immediate_work_queue->Empty()) { | 
| return false; | 
| } | 
|  | 
| base::AutoLock lock(any_thread_lock_); | 
| -  return any_thread().immediate_incoming_queue.empty(); | 
| +  return any_thread().immediate_incoming_queue.empty() && | 
| +         main_thread_only().delayed_incoming_queue.empty(); | 
| } | 
|  | 
| bool TaskQueueImpl::HasPendingImmediateWork() const { | 
| @@ -324,7 +523,7 @@ | 
| // Tasks on |delayed_incoming_queue| that could run now, count as | 
| // immediate work. | 
| if (!main_thread_only().delayed_incoming_queue.empty() && | 
| -      main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 
| +      main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= | 
| main_thread_only().time_domain->CreateLazyNow().Now()) { | 
| return true; | 
| } | 
| @@ -335,37 +534,41 @@ | 
| } | 
|  | 
| void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { | 
| -  // Enqueue all delayed tasks that should be running now, skipping any that | 
| -  // have been canceled. | 
| +  // Enqueue all delayed tasks that should be running now. | 
| while (!main_thread_only().delayed_incoming_queue.empty()) { | 
| +    DelayedRunTimeQueue::iterator next_task = | 
| +        main_thread_only().delayed_incoming_queue.begin(); | 
| +    if (next_task->delayed_run_time > lazy_now->Now()) | 
| +      break; | 
| // TODO(alexclarke): Use extract() when C++17 is allowed. | 
| -    Task& task = | 
| -        const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); | 
| -    if (task.task.IsCancelled()) { | 
| -      main_thread_only().delayed_incoming_queue.pop(); | 
| -      continue; | 
| -    } | 
| -    if (task.delayed_run_time > lazy_now->Now()) | 
| -      break; | 
| +    Task& task = const_cast<Task&>(*next_task); | 
| task.set_enqueue_order( | 
| main_thread_only().task_queue_manager->GetNextSequenceNumber()); | 
| main_thread_only().delayed_work_queue->Push(std::move(task)); | 
| -    main_thread_only().delayed_incoming_queue.pop(); | 
| -  } | 
| -} | 
| - | 
| -bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() { | 
| +    main_thread_only().delayed_incoming_queue.erase(next_task); | 
| +  } | 
| +} | 
| + | 
| +void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now) { | 
| if (!main_thread_only().task_queue_manager) | 
| -    return false; | 
| - | 
| -  if (!main_thread_only().immediate_work_queue->Empty()) | 
| -    return true; | 
| - | 
| -  base::AutoLock lock(any_thread_lock_); | 
| +    return; | 
| +  MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); | 
| +  TraceQueueSize(false); | 
| +} | 
| + | 
| +void TaskQueueImpl::UpdateImmediateWorkQueue() { | 
| +  DCHECK(main_thread_only().immediate_work_queue->Empty()); | 
| +  base::AutoLock lock(any_thread_lock_); | 
| +  if (!main_thread_only().task_queue_manager) | 
| +    return; | 
| + | 
| main_thread_only().immediate_work_queue->SwapLocked( | 
| any_thread().immediate_incoming_queue); | 
| -  // |immediate_work_queue| is now empty so updates are no longer required. | 
| -  return false; | 
| + | 
| +  // |any_thread().immediate_incoming_queue| is now empty so | 
| +  // TimeDomain::UpdateQueues no longer needs to consider this queue for | 
| +  // reloading. | 
| +  main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); | 
| } | 
|  | 
| void TaskQueueImpl::TraceQueueSize(bool is_locked) const { | 
| @@ -447,7 +650,7 @@ | 
| main_thread_only().delayed_work_queue->Size()); | 
| if (!main_thread_only().delayed_incoming_queue.empty()) { | 
| base::TimeDelta delay_to_next_task = | 
| -        (main_thread_only().delayed_incoming_queue.top().delayed_run_time - | 
| +        (main_thread_only().delayed_incoming_queue.begin()->delayed_run_time - | 
| main_thread_only().time_domain->CreateLazyNow().Now()); | 
| state->SetDouble("delay_to_next_task_ms", | 
| delay_to_next_task.InMillisecondsF()); | 
| @@ -550,9 +753,9 @@ | 
| if (!task_unblocked && previous_fence) { | 
| base::AutoLock lock(any_thread_lock_); | 
| if (!any_thread().immediate_incoming_queue.empty() && | 
| -        any_thread().immediate_incoming_queue.front().enqueue_order() > | 
| +        any_thread().immediate_incoming_queue.begin()->enqueue_order() > | 
| previous_fence && | 
| -        any_thread().immediate_incoming_queue.front().enqueue_order() < | 
| +        any_thread().immediate_incoming_queue.begin()->enqueue_order() < | 
| main_thread_only().current_fence) { | 
| task_unblocked = true; | 
| } | 
| @@ -577,7 +780,7 @@ | 
| if (!task_unblocked && previous_fence) { | 
| base::AutoLock lock(any_thread_lock_); | 
| if (!any_thread().immediate_incoming_queue.empty() && | 
| -        any_thread().immediate_incoming_queue.front().enqueue_order() > | 
| +        any_thread().immediate_incoming_queue.begin()->enqueue_order() > | 
| previous_fence) { | 
| task_unblocked = true; | 
| } | 
| @@ -602,7 +805,7 @@ | 
| if (any_thread().immediate_incoming_queue.empty()) | 
| return true; | 
|  | 
| -  return any_thread().immediate_incoming_queue.front().enqueue_order() > | 
| +  return any_thread().immediate_incoming_queue.begin()->enqueue_order() > | 
| main_thread_only().current_fence; | 
| } | 
|  | 
| @@ -618,39 +821,24 @@ | 
| if (any_thread().immediate_incoming_queue.empty()) | 
| return true; | 
|  | 
| -  return any_thread().immediate_incoming_queue.front().enqueue_order() > | 
| +  return any_thread().immediate_incoming_queue.begin()->enqueue_order() > | 
| main_thread_only().current_fence; | 
| } | 
|  | 
| // static | 
| -void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, | 
| +void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, | 
| base::trace_event::TracedValue* state) { | 
| -  // Remove const to search |queue| in the destructive manner. Restore the | 
| -  // content from |visited| later. | 
| -  std::queue<Task>* mutable_queue = const_cast<std::queue<Task>*>(&queue); | 
| -  std::queue<Task> visited; | 
| -  while (!mutable_queue->empty()) { | 
| -    TaskAsValueInto(mutable_queue->front(), state); | 
| -    visited.push(std::move(mutable_queue->front())); | 
| -    mutable_queue->pop(); | 
| -  } | 
| -  *mutable_queue = std::move(visited); | 
| +  for (const Task& task : queue) { | 
| +    TaskAsValueInto(task, state); | 
| +  } | 
| } | 
|  | 
| // static | 
| -void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue, | 
| +void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, | 
| base::trace_event::TracedValue* state) { | 
| -  // Remove const to search |queue| in the destructive manner. Restore the | 
| -  // content from |visited| later. | 
| -  std::priority_queue<Task>* mutable_queue = | 
| -      const_cast<std::priority_queue<Task>*>(&queue); | 
| -  std::priority_queue<Task> visited; | 
| -  while (!mutable_queue->empty()) { | 
| -    TaskAsValueInto(mutable_queue->top(), state); | 
| -    visited.push(std::move(const_cast<Task&>(mutable_queue->top()))); | 
| -    mutable_queue->pop(); | 
| -  } | 
| -  *mutable_queue = std::move(visited); | 
| +  for (const Task& task : queue) { | 
| +    TaskAsValueInto(task, state); | 
| +  } | 
| } | 
|  | 
| // static | 
| @@ -667,7 +855,6 @@ | 
| state->SetInteger("sequence_num", task.sequence_num); | 
| state->SetBoolean("nestable", task.nestable); | 
| state->SetBoolean("is_high_res", task.is_high_res); | 
| -  state->SetBoolean("is_cancelled", task.task.IsCancelled()); | 
| state->SetDouble( | 
| "delayed_run_time", | 
| (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 
|  |