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 |