| 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 cbfc90cdd527d88838cf21921758e75ccd0ec4bb..b2572ae4a5f682b39538e36dcc4ff0e14f989020 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
|
| @@ -147,15 +147,17 @@ void TaskQueueManager::UnregisterTaskQueue(
|
| selector_.RemoveQueue(task_queue.get());
|
| }
|
|
|
| -void TaskQueueManager::UpdateWorkQueues(LazyNow lazy_now) {
|
| +void TaskQueueManager::UpdateWorkQueues(LazyNow* lazy_now) {
|
| TRACE_EVENT0(disabled_by_default_tracing_category_,
|
| "TaskQueueManager::UpdateWorkQueues");
|
|
|
| for (TimeDomain* time_domain : time_domains_) {
|
| - LazyNow lazy_now_in_domain = time_domain == real_time_domain_.get()
|
| - ? lazy_now
|
| - : time_domain->CreateLazyNow();
|
| - time_domain->UpdateWorkQueues(lazy_now_in_domain);
|
| + if (time_domain == real_time_domain_.get()) {
|
| + time_domain->UpdateWorkQueues(lazy_now);
|
| + } else {
|
| + LazyNow time_domain_lazy_now = time_domain->CreateLazyNow();
|
| + time_domain->UpdateWorkQueues(&time_domain_lazy_now);
|
| + }
|
| }
|
| }
|
|
|
| @@ -232,14 +234,15 @@ void TaskQueueManager::DoWork(base::TimeTicks run_time, bool from_main_thread) {
|
| queues_to_delete_.clear();
|
|
|
| LazyNow lazy_now(real_time_domain()->CreateLazyNow());
|
| - UpdateWorkQueues(lazy_now);
|
| + UpdateWorkQueues(&lazy_now);
|
|
|
| for (int i = 0; i < work_batch_size_; i++) {
|
| internal::WorkQueue* work_queue;
|
| if (!SelectWorkQueueToService(&work_queue))
|
| break;
|
|
|
| - switch (ProcessTaskFromWorkQueue(work_queue, &lazy_now)) {
|
| + base::TimeTicks time_after_task;
|
| + switch (ProcessTaskFromWorkQueue(work_queue, lazy_now, &time_after_task)) {
|
| case ProcessTaskResult::DEFERRED:
|
| // If a task was deferred, try again with another task.
|
| continue;
|
| @@ -251,7 +254,9 @@ void TaskQueueManager::DoWork(base::TimeTicks run_time, bool from_main_thread) {
|
|
|
| work_queue = nullptr; // The queue may have been unregistered.
|
|
|
| - UpdateWorkQueues(lazy_now);
|
| + lazy_now = time_after_task.is_null() ? real_time_domain()->CreateLazyNow()
|
| + : LazyNow(time_after_task);
|
| + UpdateWorkQueues(&lazy_now);
|
|
|
| // Only run a single task per batch in nested run loops so that we can
|
| // properly exit the nested loop when someone calls RunLoop::Quit().
|
| @@ -264,16 +269,38 @@ void TaskQueueManager::DoWork(base::TimeTicks run_time, bool from_main_thread) {
|
| // TODO(alexclarke): Consider refactoring the above loop to terminate only
|
| // when there's no more work left to be done, rather than posting a
|
| // continuation task.
|
| - if (!selector_.EnabledWorkQueuesEmpty() || TryAdvanceTimeDomains())
|
| + base::Optional<base::TimeDelta> next_delay =
|
| + ComputeDelayTillNextTask(&lazy_now);
|
| +
|
| + if (!next_delay)
|
| + return;
|
| +
|
| + base::TimeDelta delay = next_delay.value();
|
| + if (delay.is_zero()) {
|
| MaybeScheduleImmediateWork(FROM_HERE);
|
| + } else {
|
| + MaybeScheduleDelayedWork(FROM_HERE, lazy_now.Now(), delay);
|
| + }
|
| }
|
|
|
| -bool TaskQueueManager::TryAdvanceTimeDomains() {
|
| - bool can_advance = false;
|
| +base::Optional<base::TimeDelta> TaskQueueManager::ComputeDelayTillNextTask(
|
| + LazyNow* lazy_now) {
|
| + // If the selector has non-empty queues we trivially know there is immediate
|
| + // work to be done.
|
| + if (!selector_.EnabledWorkQueuesEmpty())
|
| + return base::TimeDelta();
|
| +
|
| + // Otherwise we need to find the shortest delay, if any.
|
| + base::Optional<base::TimeDelta> next_continuation;
|
| for (TimeDomain* time_domain : time_domains_) {
|
| - can_advance |= time_domain->MaybeAdvanceTime();
|
| + base::Optional<base::TimeDelta> continuation =
|
| + time_domain->DelayTillNextTask(lazy_now);
|
| + if (!continuation)
|
| + continue;
|
| + if (!next_continuation || next_continuation.value() > continuation.value())
|
| + next_continuation = continuation;
|
| }
|
| - return can_advance;
|
| + return next_continuation;
|
| }
|
|
|
| bool TaskQueueManager::SelectWorkQueueToService(
|
| @@ -292,7 +319,8 @@ void TaskQueueManager::DidQueueTask(
|
|
|
| TaskQueueManager::ProcessTaskResult TaskQueueManager::ProcessTaskFromWorkQueue(
|
| internal::WorkQueue* work_queue,
|
| - LazyNow* lazy_now) {
|
| + LazyNow time_before_task,
|
| + base::TimeTicks* time_after_task) {
|
| DCHECK(main_thread_checker_.CalledOnValidThread());
|
| scoped_refptr<DeletionSentinel> protect(deletion_sentinel_);
|
| internal::TaskQueueImpl::Task pending_task =
|
| @@ -332,7 +360,7 @@ TaskQueueManager::ProcessTaskResult TaskQueueManager::ProcessTaskFromWorkQueue(
|
| bool notify_time_observers =
|
| !delegate_->IsNested() && task_time_observers_.might_have_observers();
|
| if (notify_time_observers) {
|
| - task_start_time = MonotonicTimeInSeconds(lazy_now->Now());
|
| + task_start_time = MonotonicTimeInSeconds(time_before_task.Now());
|
| for (auto& observer : task_time_observers_)
|
| observer.willProcessTask(queue, task_start_time);
|
| }
|
| @@ -354,11 +382,11 @@ TaskQueueManager::ProcessTaskResult TaskQueueManager::ProcessTaskFromWorkQueue(
|
|
|
| currently_executing_task_queue_ = prev_executing_task_queue;
|
|
|
| - *lazy_now = real_time_domain()->CreateLazyNow();
|
|
|
| if (queue->GetShouldNotifyObservers()) {
|
| if (task_start_time) {
|
| - double task_end_time = MonotonicTimeInSeconds(lazy_now->Now());
|
| + *time_after_task = real_time_domain()->Now();
|
| + double task_end_time = MonotonicTimeInSeconds(*time_after_task);
|
| for (auto& observer : task_time_observers_)
|
| observer.didProcessTask(queue, task_start_time, task_end_time);
|
| }
|
| @@ -409,7 +437,8 @@ void TaskQueueManager::RemoveTaskObserver(
|
| task_observers_.RemoveObserver(task_observer);
|
| }
|
|
|
| -void TaskQueueManager::AddTaskTimeObserver(TaskTimeObserver* task_time_observer) {
|
| +void TaskQueueManager::AddTaskTimeObserver(
|
| + TaskTimeObserver* task_time_observer) {
|
| DCHECK(main_thread_checker_.CalledOnValidThread());
|
| task_time_observers_.AddObserver(task_time_observer);
|
| }
|
|
|