Index: components/scheduler/base/delayed_task_delegate.cc |
diff --git a/components/scheduler/base/delayed_task_delegate.cc b/components/scheduler/base/delayed_task_delegate.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2ddc1726705d27f6181401433ca9d49b285a842b |
--- /dev/null |
+++ b/components/scheduler/base/delayed_task_delegate.cc |
@@ -0,0 +1,86 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "components/scheduler/base/delayed_task_delegate.h" |
+ |
+#include <set> |
+ |
+#include "components/scheduler/base/task_queue_impl.h" |
+#include "components/scheduler/base/task_queue_manager_delegate.h" |
+#include "components/scheduler/scheduler_export.h" |
+ |
+namespace scheduler { |
+ |
+DelayedTaskDelegate::DelayedTaskDelegate() {} |
+ |
+DelayedTaskDelegate::~DelayedTaskDelegate() {} |
+ |
+void DelayedTaskDelegate::ScheduleDelayedWork( |
+ internal::TaskQueueImpl* queue, |
+ base::TimeTicks delayed_run_time) { |
+ if (!BelongsToCurrentThread()) { |
+ // NOTE posting a delayed task from a different thread is not expected to be |
+ // common. This pathway is less optimal than perhaps it could be because |
+ // it causes two main thread tasks to be run. Should this assumption prove |
+ // to be false in future, we may need to revisit this. |
+ PostScheduleDelayedWorkTaskOnMainThread(queue, delayed_run_time); |
+ return; |
+ } |
+ |
+ // Make sure there's one (and only one) task posted to |delegate_| |
+ // to call |DelayedDoWork| at |delayed_run_time|. |
+ if (delayed_wakeup_multimap_.find(delayed_run_time) == |
+ delayed_wakeup_multimap_.end()) { |
+ base::TimeDelta delay = |
+ std::max(base::TimeDelta(), delayed_run_time - CachedNow()); |
+ ScheduleDoWork(delay); |
+ } |
+ delayed_wakeup_multimap_.insert(std::make_pair(delayed_run_time, queue)); |
+} |
+ |
+void DelayedTaskDelegate::ScheduleDelayedWorkTask( |
+ scoped_refptr<internal::TaskQueueImpl> queue, |
+ base::TimeTicks delayed_run_time) { |
+ InvalidateNowCache(); |
+ ScheduleDelayedWork(queue.get(), delayed_run_time); |
+} |
+ |
+void DelayedTaskDelegate::CancelDelayedWork(internal::TaskQueueImpl* 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) { |
+ DelayedWakeupMultimap::iterator temp = iter; |
+ iter++; |
+ // O(1) amortized. |
+ delayed_wakeup_multimap_.erase(temp); |
+ } else { |
+ iter++; |
+ } |
+ } |
+} |
+ |
+void DelayedTaskDelegate::WakeupReadyDelayedQueues() { |
+ // 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 > CachedNow()) |
+ break; |
+ // A queue could have any number of delayed tasks pending so it's worthwhile |
+ // deduping calls to MoveReadyDelayedTasksToIncomingQueue 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->MoveReadyDelayedTasksToIncomingQueue(); |
+ delayed_wakeup_multimap_.erase(next_wakeup); |
+ } |
+} |
+ |
+} // namespace scheduler |