Chromium Code Reviews| Index: third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc |
| diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc |
| index e42fee10c09e0aa1542725e07936804dca855cc6..933800c87086f042e157e296b2d320dd4dfcd4c2 100644 |
| --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc |
| +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc |
| @@ -230,10 +230,10 @@ void TaskQueueManager::MaybeScheduleImmediateWorkLocked( |
| void TaskQueueManager::MaybeScheduleDelayedWork( |
| const tracked_objects::Location& from_here, |
| - base::TimeTicks now, |
| - base::TimeDelta delay) { |
| + TimeDomain* requesting_time_domain, |
| + LazyNow* lazy_now, |
| + base::TimeTicks run_time) { |
| DCHECK(main_thread_checker_.CalledOnValidThread()); |
|
Sami
2017/02/01 07:30:05
DCHECK(!next_delayed_do_work_ || next_delayed_do_w
alex clarke (OOO till 29th)
2017/02/01 14:50:11
Done.
|
| - DCHECK_GE(delay, base::TimeDelta()); |
| { |
| base::AutoLock lock(any_thread_lock_); |
| @@ -248,21 +248,35 @@ void TaskQueueManager::MaybeScheduleDelayedWork( |
| } |
| // De-duplicate DoWork posts. |
| - base::TimeTicks run_time = now + delay; |
| - if (next_scheduled_delayed_do_work_time_ <= run_time && |
| - !next_scheduled_delayed_do_work_time_.is_null()) |
| + if (next_delayed_do_work_ && next_delayed_do_work_.run_time() <= run_time) |
| return; |
| + cancelable_delayed_do_work_closure_.Reset(delayed_do_work_closure_); |
| + |
| + base::TimeDelta delay = |
| + std::max(base::TimeDelta(), run_time - lazy_now->Now()); |
| + |
| TRACE_EVENT1(disabled_by_default_tracing_category_, |
| "TaskQueueManager::MaybeScheduleDelayedWork::PostDelayedTask", |
| "delay_ms", delay.InMillisecondsF()); |
| cancelable_delayed_do_work_closure_.Reset(delayed_do_work_closure_); |
| - next_scheduled_delayed_do_work_time_ = run_time; |
| + next_delayed_do_work_ = NextDelayedDoWork(run_time, requesting_time_domain); |
| delegate_->PostDelayedTask( |
| from_here, cancelable_delayed_do_work_closure_.callback(), delay); |
| } |
| +void TaskQueueManager::CancelDelayedWork(TimeDomain* requesting_time_domain, |
| + base::TimeTicks run_time) { |
| + DCHECK(main_thread_checker_.CalledOnValidThread()); |
| + if (next_delayed_do_work_.run_time() != run_time) |
| + return; |
| + |
| + DCHECK_EQ(next_delayed_do_work_.time_domain(), requesting_time_domain); |
| + cancelable_delayed_do_work_closure_.Cancel(); |
| + next_delayed_do_work_.Clear(); |
| +} |
| + |
| void TaskQueueManager::DoWork(bool delayed) { |
| DCHECK(main_thread_checker_.CalledOnValidThread()); |
| TRACE_EVENT1(tracing_category_, "TaskQueueManager::DoWork", "delayed", |
| @@ -275,9 +289,10 @@ void TaskQueueManager::DoWork(bool delayed) { |
| // This must be done before running any tasks because they could invoke a |
| // nested message loop and we risk having a stale |
| - // |next_scheduled_delayed_do_work_time_|. |
| + // |next_delayed_do_work_|. |
|
Sami
2017/02/01 07:30:04
nit: rewrap
alex clarke (OOO till 29th)
2017/02/01 14:50:11
Done.
|
| if (delayed) |
| - next_scheduled_delayed_do_work_time_ = base::TimeTicks(); |
| + next_delayed_do_work_.Clear(); |
| + ; |
|
Sami
2017/02/01 07:30:04
Extra ';'?
alex clarke (OOO till 29th)
2017/02/01 14:50:11
Done.
|
| for (int i = 0; i < work_batch_size_; i++) { |
| IncomingImmediateWorkMap queues_to_reload; |
| @@ -339,7 +354,7 @@ void TaskQueueManager::DoWork(bool delayed) { |
| { |
| MoveableAutoLock lock(any_thread_lock_); |
| - base::Optional<base::TimeDelta> next_delay = |
| + base::Optional<NextTaskDelay> next_delay = |
| ComputeDelayTillNextTaskLocked(&lazy_now); |
| any_thread().do_work_running_count--; |
| @@ -353,7 +368,7 @@ void TaskQueueManager::DoWork(bool delayed) { |
| } |
| void TaskQueueManager::PostDoWorkContinuationLocked( |
| - base::Optional<base::TimeDelta> next_delay, |
| + base::Optional<NextTaskDelay> next_delay, |
| LazyNow* lazy_now, |
| MoveableAutoLock&& lock) { |
| DCHECK(main_thread_checker_.CalledOnValidThread()); |
| @@ -365,8 +380,8 @@ void TaskQueueManager::PostDoWorkContinuationLocked( |
| // If there are no tasks left then we don't need to post a continuation. |
| if (!next_delay) { |
| // If there's a pending delayed DoWork, cancel it because it's not needed. |
| - if (!next_scheduled_delayed_do_work_time_.is_null()) { |
| - next_scheduled_delayed_do_work_time_ = base::TimeTicks(); |
| + if (next_delayed_do_work_) { |
| + next_delayed_do_work_.Clear(); |
| cancelable_delayed_do_work_closure_.Cancel(); |
| } |
| return; |
| @@ -376,7 +391,7 @@ void TaskQueueManager::PostDoWorkContinuationLocked( |
| if (any_thread().immediate_do_work_posted_count > 0) |
| return; |
| - delay = next_delay.value(); |
| + delay = next_delay->delay(); |
| // This isn't supposed to happen, but in case it does convert to |
| // non-delayed. |
| @@ -386,18 +401,12 @@ void TaskQueueManager::PostDoWorkContinuationLocked( |
| if (delay.is_zero()) { |
| // If a delayed DoWork is pending then we don't need to post a |
| // continuation because it should run immediately. |
| - if (!next_scheduled_delayed_do_work_time_.is_null() && |
| - next_scheduled_delayed_do_work_time_ <= lazy_now->Now()) { |
| + if (next_delayed_do_work_ && |
| + next_delayed_do_work_.run_time() <= lazy_now->Now()) { |
| return; |
| } |
| any_thread().immediate_do_work_posted_count++; |
| - } else { |
| - base::TimeTicks run_time = lazy_now->Now() + delay; |
| - if (next_scheduled_delayed_do_work_time_ == run_time) |
| - return; |
| - |
| - next_scheduled_delayed_do_work_time_ = run_time; |
| } |
| } |
| @@ -405,13 +414,19 @@ void TaskQueueManager::PostDoWorkContinuationLocked( |
| if (delay.is_zero()) { |
| delegate_->PostTask(FROM_HERE, immediate_do_work_closure_); |
| } else { |
| + base::TimeTicks run_time = lazy_now->Now() + delay; |
| + if (next_delayed_do_work_.run_time() == run_time) |
| + return; |
| + |
| + next_delayed_do_work_ = |
| + NextDelayedDoWork(run_time, next_delay->time_domain()); |
| cancelable_delayed_do_work_closure_.Reset(delayed_do_work_closure_); |
| delegate_->PostDelayedTask( |
| FROM_HERE, cancelable_delayed_do_work_closure_.callback(), delay); |
| } |
| } |
| -base::Optional<base::TimeDelta> |
| +base::Optional<TaskQueueManager::NextTaskDelay> |
| TaskQueueManager::ComputeDelayTillNextTaskLocked(LazyNow* lazy_now) { |
| DCHECK(main_thread_checker_.CalledOnValidThread()); |
| @@ -420,27 +435,32 @@ TaskQueueManager::ComputeDelayTillNextTaskLocked(LazyNow* lazy_now) { |
| // check is equavalent to calling ReloadEmptyWorkQueues first. |
| for (const auto& pair : any_thread().has_incoming_immediate_work) { |
| if (pair.first->CouldTaskRun(pair.second)) |
| - return base::TimeDelta(); |
| + return NextTaskDelay(); |
| } |
| // If the selector has non-empty queues we trivially know there is immediate |
| // work to be done. |
| if (!selector_.EnabledWorkQueuesEmpty()) |
| - return base::TimeDelta(); |
| + return NextTaskDelay(); |
| // Otherwise we need to find the shortest delay, if any. NB we don't need to |
| // call WakeupReadyDelayedQueues because it's assumed DelayTillNextTask will |
| // return base::TimeDelta>() if the delayed task is due to run now. |
| - base::Optional<base::TimeDelta> next_continuation; |
| + base::Optional<NextTaskDelay> delay_till_next_task; |
| for (TimeDomain* time_domain : time_domains_) { |
| - base::Optional<base::TimeDelta> continuation = |
| + base::Optional<base::TimeDelta> delay = |
| time_domain->DelayTillNextTask(lazy_now); |
| - if (!continuation) |
| + if (!delay) |
| continue; |
| - if (!next_continuation || next_continuation.value() > continuation.value()) |
| - next_continuation = continuation; |
| + |
| + NextTaskDelay task_delay = (delay.value() == base::TimeDelta()) |
| + ? NextTaskDelay() |
| + : NextTaskDelay(delay.value(), time_domain); |
| + |
| + if (!delay_till_next_task || task_delay < delay_till_next_task.value()) |
| + delay_till_next_task = task_delay; |
| } |
| - return next_continuation; |
| + return delay_till_next_task; |
| } |
| bool TaskQueueManager::SelectWorkQueueToService( |