Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/task_scheduler/delayed_task_manager.h" | |
| 6 | |
| 7 #include <utility> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/logging.h" | |
| 11 | |
| 12 namespace base { | |
| 13 namespace internal { | |
| 14 | |
| 15 DelayedTaskManager::DelayedTaskManager(const Closure& delayed_run_time_changed) | |
| 16 : delayed_run_time_changed_(delayed_run_time_changed) { | |
| 17 DCHECK(!delayed_run_time_changed_.is_null()); | |
| 18 } | |
| 19 | |
| 20 DelayedTaskManager::~DelayedTaskManager() = default; | |
| 21 | |
| 22 void DelayedTaskManager::AddDelayedTask( | |
| 23 std::unique_ptr<Task> task, | |
| 24 const PostTaskCallback& post_task_callback) { | |
| 25 DCHECK(task); | |
| 26 DCHECK(!post_task_callback.is_null()); | |
| 27 | |
| 28 const TimeTicks new_task_delayed_run_time = task->delayed_run_time; | |
| 29 TimeTicks previous_delayed_run_time; | |
| 30 | |
| 31 { | |
| 32 AutoSchedulerLock auto_lock(lock_); | |
| 33 | |
| 34 DelayedTask delayed_task; | |
| 35 delayed_task.task = std::move(task); | |
| 36 delayed_task.post_task_callback = post_task_callback; | |
| 37 delayed_task.index = next_delayed_task_index_++; | |
| 38 | |
| 39 if (!delayed_tasks_.empty()) | |
|
robliao
2016/04/01 20:48:25
Let's move this before the DelayedTask block above
fdoray
2016/04/01 21:21:57
Done.
| |
| 40 previous_delayed_run_time = delayed_tasks_.top().task->delayed_run_time; | |
| 41 | |
| 42 delayed_tasks_.emplace(std::move(delayed_task)); | |
| 43 } | |
| 44 | |
| 45 if (previous_delayed_run_time.is_null() || | |
| 46 new_task_delayed_run_time < previous_delayed_run_time) { | |
| 47 delayed_run_time_changed_.Run(); | |
| 48 } | |
| 49 } | |
| 50 | |
| 51 void DelayedTaskManager::PostReadyTasks() { | |
| 52 const TimeTicks now = Now(); | |
| 53 | |
| 54 // Move delayed tasks that are ready for execution into |ready_tasks|. Don't | |
| 55 // post them right away to avoid imposing an unecessary lock dependency on | |
| 56 // callbacks. | |
| 57 std::vector<DelayedTask> ready_tasks; | |
| 58 | |
| 59 { | |
| 60 AutoSchedulerLock auto_lock(lock_); | |
| 61 while (!delayed_tasks_.empty() && | |
| 62 delayed_tasks_.top().task->delayed_run_time <= now) { | |
| 63 // The const_cast for std::move is almost okay since we're immediately | |
| 64 // moving it to |ready_tasks|. See DelayedTask::operator< for why it's | |
| 65 // almost. | |
| 66 ready_tasks.push_back( | |
|
robliao
2016/04/01 20:48:25
This can be an emplace_back.
fdoray
2016/04/01 21:21:57
Done.
| |
| 67 std::move(const_cast<DelayedTask&>(delayed_tasks_.top()))); | |
| 68 delayed_tasks_.pop(); | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 // Post delayed tasks that are ready for execution. | |
| 73 for (auto& delayed_task : ready_tasks) | |
| 74 delayed_task.post_task_callback.Run(std::move(delayed_task.task)); | |
| 75 } | |
| 76 | |
| 77 TimeTicks DelayedTaskManager::GetNextDelayedRunTime() const { | |
| 78 AutoSchedulerLock auto_lock(lock_); | |
| 79 | |
| 80 if (delayed_tasks_.empty()) | |
| 81 return TimeTicks(); | |
| 82 | |
| 83 return delayed_tasks_.top().task->delayed_run_time; | |
| 84 } | |
| 85 | |
| 86 TimeTicks DelayedTaskManager::Now() { | |
| 87 return TimeTicks::Now(); | |
| 88 } | |
| 89 | |
| 90 DelayedTaskManager::DelayedTask::DelayedTask() = default; | |
| 91 | |
| 92 DelayedTaskManager::DelayedTask::~DelayedTask() = default; | |
| 93 | |
| 94 DelayedTaskManager::DelayedTask::DelayedTask(DelayedTask&& other) | |
| 95 : task(std::move(other.task)), | |
| 96 post_task_callback(other.post_task_callback), | |
| 97 index(other.index) {} | |
| 98 | |
| 99 DelayedTaskManager::DelayedTask& DelayedTaskManager::DelayedTask::operator=( | |
| 100 DelayedTask&& other) { | |
| 101 task = std::move(other.task); | |
| 102 post_task_callback = other.post_task_callback; | |
| 103 index = other.index; | |
| 104 return *this; | |
| 105 } | |
| 106 | |
| 107 bool DelayedTaskManager::DelayedTask::operator<( | |
| 108 const DelayedTask& other) const { | |
| 109 // Due to STL consistency checks in Windows and const_cast'ing right before | |
| 110 // popping the DelayedTask, we might actually have null tasks. | |
| 111 // To keep the order of the data structure the same, we consider null tasks | |
| 112 // to be the smallest possible |delayed_run_time|. | |
| 113 if (!task) | |
| 114 return false; | |
| 115 if (!other.task) | |
| 116 return true; | |
| 117 if (task->delayed_run_time > other.task->delayed_run_time) | |
| 118 return true; | |
| 119 if (task->delayed_run_time < other.task->delayed_run_time) | |
| 120 return false; | |
| 121 return index > other.index; | |
| 122 } | |
| 123 | |
| 124 } // namespace internal | |
| 125 } // namespace base | |
| OLD | NEW |