| Index: third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
|
| diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
|
| index 3093132d23a9c932bd99b8be8d4787800dfeca79..d1713ce324790080ab3bdf1c4674aca6165b6d8f 100644
|
| --- a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
|
| +++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
|
| @@ -29,17 +29,17 @@ void TimeDomain::UnregisterQueue(internal::TaskQueueImpl* queue) {
|
| DCHECK_EQ(queue->GetTimeDomain(), this);
|
| UnregisterAsUpdatableTaskQueue(queue);
|
|
|
| - // We need to remove |task_queue| from delayed_wakeup_multimap_ which is a
|
| - // little awkward since it's keyed by time. O(n) running time.
|
| - for (DelayedWakeupMultimap::iterator iter = delayed_wakeup_multimap_.begin();
|
| - iter != delayed_wakeup_multimap_.end();) {
|
| - if (iter->second == queue) {
|
| - // O(1) amortized.
|
| - iter = delayed_wakeup_multimap_.erase(iter);
|
| - } else {
|
| - iter++;
|
| - }
|
| - }
|
| + // If present remove |task_queue| from delayed_wakeup_multimap_.
|
| + // O(log n)
|
| + QueueToDelayedWakeupMultimapIteratorMap::iterator it =
|
| + queue_to_delayed_wakeup_multimap_iterator_map_.find(queue);
|
| +
|
| + if (it == queue_to_delayed_wakeup_multimap_iterator_map_.end())
|
| + return;
|
| +
|
| + // O(1) amortized.
|
| + delayed_wakeup_multimap_.erase(it->second);
|
| + queue_to_delayed_wakeup_multimap_iterator_map_.erase(it);
|
| }
|
|
|
| void TimeDomain::MigrateQueue(internal::TaskQueueImpl* queue,
|
| @@ -53,74 +53,55 @@ void TimeDomain::MigrateQueue(internal::TaskQueueImpl* queue,
|
| if (UnregisterAsUpdatableTaskQueue(queue))
|
| destination_time_domain->updatable_queue_set_.insert(queue);
|
|
|
| + // If present remove |task_queue| from delayed_wakeup_multimap_.
|
| + // O(log n)
|
| + QueueToDelayedWakeupMultimapIteratorMap::iterator it =
|
| + queue_to_delayed_wakeup_multimap_iterator_map_.find(queue);
|
| +
|
| + if (it == queue_to_delayed_wakeup_multimap_iterator_map_.end())
|
| + return;
|
| +
|
| base::TimeTicks destination_now = destination_time_domain->Now();
|
| - // We need to remove |task_queue| from delayed_wakeup_multimap_ which is a
|
| - // little awkward since it's keyed by time. O(n) running time.
|
| - for (DelayedWakeupMultimap::iterator iter = delayed_wakeup_multimap_.begin();
|
| - iter != delayed_wakeup_multimap_.end();) {
|
| - if (iter->second == queue) {
|
| - destination_time_domain->ScheduleDelayedWork(queue, iter->first,
|
| - destination_now);
|
| - // O(1) amortized.
|
| - iter = delayed_wakeup_multimap_.erase(iter);
|
| - } else {
|
| - iter++;
|
| - }
|
| - }
|
| + destination_time_domain->ScheduleDelayedWork(queue, it->second->first,
|
| + destination_now);
|
| +
|
| + // O(1) amortized.
|
| + delayed_wakeup_multimap_.erase(it->second);
|
| + queue_to_delayed_wakeup_multimap_iterator_map_.erase(it);
|
| }
|
|
|
| void TimeDomain::ScheduleDelayedWork(internal::TaskQueueImpl* queue,
|
| base::TimeTicks delayed_run_time,
|
| base::TimeTicks now) {
|
| DCHECK(main_thread_checker_.CalledOnValidThread());
|
| + // We only want to store a single wakeup per queue, so we need to remove any
|
| + // previously registered wake up for |queue|.
|
| + QueueToDelayedWakeupMultimapIteratorMap::iterator it =
|
| + queue_to_delayed_wakeup_multimap_iterator_map_.find(queue);
|
| +
|
| + if (it != queue_to_delayed_wakeup_multimap_iterator_map_.end())
|
| + delayed_wakeup_multimap_.erase(it->second);
|
| +
|
| if (delayed_wakeup_multimap_.empty() ||
|
| delayed_run_time < delayed_wakeup_multimap_.begin()->first) {
|
| base::TimeDelta delay = std::max(base::TimeDelta(), delayed_run_time - now);
|
| RequestWakeup(now, delay);
|
| }
|
|
|
| - delayed_wakeup_multimap_.insert(std::make_pair(delayed_run_time, queue));
|
| + if (it != queue_to_delayed_wakeup_multimap_iterator_map_.end()) {
|
| + // TODO(alexclarke): Use C++17 extract & insert to more efficiently modify
|
| + // |queue_to_delayed_wakeup_multimap_iterator_map_|.
|
| + it->second = delayed_wakeup_multimap_.insert({delayed_run_time, queue});
|
| + } else {
|
| + // Insert the wakeup and store the map iterator for later convenience.
|
| + queue_to_delayed_wakeup_multimap_iterator_map_.insert(
|
| + {queue, delayed_wakeup_multimap_.insert({delayed_run_time, queue})});
|
| + }
|
| +
|
| if (observer_)
|
| observer_->OnTimeDomainHasDelayedWork();
|
| }
|
|
|
| -void TimeDomain::CancelDelayedWork(internal::TaskQueueImpl* queue,
|
| - base::TimeTicks delayed_run_time) {
|
| - DCHECK(main_thread_checker_.CalledOnValidThread());
|
| -
|
| - auto iterpair = delayed_wakeup_multimap_.equal_range(delayed_run_time);
|
| - for (auto it = iterpair.first; it != iterpair.second; ++it) {
|
| - if (it->second == queue) {
|
| - base::TimeTicks prev_first_wakeup =
|
| - delayed_wakeup_multimap_.begin()->first;
|
| -
|
| - // Note we only erase the entry corresponding to |queue|, there might be
|
| - // other queues that happen to require a wake up at |delayed_run_time|
|
| - // which we must respect.
|
| - delayed_wakeup_multimap_.erase(it);
|
| -
|
| - // If |delayed_wakeup_multimap_| is now empty, there's nothing to be done.
|
| - // Sadly the base TaskRunner does and some OSes don't support cancellation
|
| - // so we can't cancel something requested with RequestWakeup.
|
| - if (delayed_wakeup_multimap_.empty())
|
| - break;
|
| -
|
| - base::TimeTicks first_wakeup = delayed_wakeup_multimap_.begin()->first;
|
| -
|
| - // If the first_wakeup hasn't changed we don't need to do anything, the
|
| - // wakeup was already requested.
|
| - if (first_wakeup == prev_first_wakeup)
|
| - break;
|
| -
|
| - // The first wakeup has changed, we need to re-schedule.
|
| - base::TimeTicks now = Now();
|
| - base::TimeDelta delay = std::max(base::TimeDelta(), first_wakeup - now);
|
| - RequestWakeup(now, delay);
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| void TimeDomain::RegisterAsUpdatableTaskQueue(internal::TaskQueueImpl* queue) {
|
| {
|
| base::AutoLock lock(newly_updatable_lock_);
|
| @@ -186,33 +167,20 @@ void TimeDomain::WakeupReadyDelayedQueues(LazyNow* lazy_now) {
|
| // Wake up any queues with pending delayed work. Note std::multipmap stores
|
| // the elements sorted by key, so the begin() iterator points to the earliest
|
| // queue to wakeup.
|
| - std::set<internal::TaskQueueImpl*> dedup_set;
|
| while (!delayed_wakeup_multimap_.empty()) {
|
| DelayedWakeupMultimap::iterator next_wakeup =
|
| delayed_wakeup_multimap_.begin();
|
| if (next_wakeup->first > lazy_now->Now())
|
| break;
|
| - // A queue could have any number of delayed tasks pending so it's worthwhile
|
| - // deduping calls to UpdateDelayedWorkQueue since it takes a lock.
|
| - // NOTE the order in which these are called matters since the order
|
| - // in which EnqueueTaskLocks is called is respected when choosing which
|
| - // queue to execute a task from.
|
| - if (dedup_set.insert(next_wakeup->second).second) {
|
| - next_wakeup->second->MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now);
|
| - }
|
| - delayed_wakeup_multimap_.erase(next_wakeup);
|
| - }
|
| -}
|
|
|
| -void TimeDomain::ClearExpiredWakeups() {
|
| - DCHECK(main_thread_checker_.CalledOnValidThread());
|
| - LazyNow lazy_now(CreateLazyNow());
|
| - while (!delayed_wakeup_multimap_.empty()) {
|
| - DelayedWakeupMultimap::iterator next_wakeup =
|
| - delayed_wakeup_multimap_.begin();
|
| - if (next_wakeup->first > lazy_now.Now())
|
| - break;
|
| + internal::TaskQueueImpl* queue = next_wakeup->second;
|
| +
|
| + // O(1) amortized.
|
| delayed_wakeup_multimap_.erase(next_wakeup);
|
| + // O(log n).
|
| + queue_to_delayed_wakeup_multimap_iterator_map_.erase(queue);
|
| +
|
| + queue->WakeUpForDelayedWork(lazy_now);
|
| }
|
| }
|
|
|
|
|