Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(632)

Side by Side Diff: base/task_scheduler/delayed_task_manager.cc

Issue 1806473002: TaskScheduler [9] Delayed Task Manager (Closed) Base URL: https://luckyluke-private.googlesource.com/src@s_5_worker_thread
Patch Set: self review Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
9 #include "base/logging.h"
10 #include "base/task_scheduler/utils.h"
11
12 namespace base {
13 namespace internal {
14
15 struct DelayedTaskManager::DelayedTask {
16 DelayedTask(std::unique_ptr<Task> task,
17 scoped_refptr<Sequence> sequence,
18 PriorityQueue* priority_queue,
19 size_t index)
20 : task(std::move(task)),
21 sequence(std::move(sequence)),
22 priority_queue(priority_queue),
23 index(index) {}
24
25 DelayedTask(DelayedTask&& other)
26 : task(std::move(other.task)),
27 sequence(std::move(other.sequence)),
28 priority_queue(other.priority_queue),
29 index(other.index) {}
30
31 ~DelayedTask() = default;
32
33 DelayedTask& operator=(DelayedTask&& other) {
34 task = std::move(other.task);
35 sequence = std::move(other.sequence);
36 priority_queue = other.priority_queue;
37 index = other.index;
38 return *this;
39 }
40
41 std::unique_ptr<Task> task;
42
43 // The sequence and priority queue in which |task| is inserted once it
44 // becomes ripe for execution.
45 scoped_refptr<Sequence> sequence;
46 PriorityQueue* priority_queue;
47
48 // Ensures that tasks that have the same |delayed_run_time| are sorted
49 // according to the order in which they were added to the DelayedTaskManager.
50 size_t index;
51
52 private:
53 DISALLOW_COPY_AND_ASSIGN(DelayedTask);
54 };
55
56 DelayedTaskManager::DelayedTaskManager(
57 const Closure& on_next_delayed_run_time_updated)
58 : on_next_delayed_run_time_updated_(on_next_delayed_run_time_updated) {
59 DCHECK(!on_next_delayed_run_time_updated_.is_null());
60 }
61
62 DelayedTaskManager::~DelayedTaskManager() = default;
63
64 void DelayedTaskManager::AddDelayedTask(std::unique_ptr<Task> task,
65 scoped_refptr<Sequence> sequence,
66 PriorityQueue* priority_queue) {
67 DCHECK(task);
68 DCHECK(sequence);
69 DCHECK(priority_queue);
70
71 const TimeTicks new_task_delayed_run_time = task->delayed_run_time;
72 TimeTicks existing_next_delayed_run_time;
gab 2016/04/11 18:28:30 How about s/existing_next_delayed_run_time/current
fdoray 2016/04/11 19:57:05 Done.
73
74 {
75 AutoSchedulerLock auto_lock(lock_);
76
77 if (!delayed_tasks_.empty()) {
78 existing_next_delayed_run_time =
79 delayed_tasks_.top().task->delayed_run_time;
80 }
81
82 delayed_tasks_.emplace(std::move(task), std::move(sequence), priority_queue,
83 next_delayed_task_index_++);
84 }
85
86 if (existing_next_delayed_run_time.is_null() ||
87 new_task_delayed_run_time < existing_next_delayed_run_time) {
88 on_next_delayed_run_time_updated_.Run();
89 }
90 }
91
92 void DelayedTaskManager::PostReadyTasks() {
93 const TimeTicks now = Now();
94
95 // Move delayed tasks that are ready for execution into |ready_tasks|. Don't
96 // post them right away to avoid imposing an unecessary lock dependency on
97 // PostTaskNowHelper.
98 std::vector<DelayedTask> ready_tasks;
99
100 {
101 AutoSchedulerLock auto_lock(lock_);
102 while (!delayed_tasks_.empty() &&
103 delayed_tasks_.top().task->delayed_run_time <= now) {
104 // The const_cast for std::move is almost okay since we're immediately
gab 2016/04/11 18:28:30 "almost okay" sound weird here, how about: // The
fdoray 2016/04/11 19:57:06 Done.
105 // moving it to |ready_tasks|. See DelayedTaskComparator::operator() for
106 // why it's almost.
107 ready_tasks.emplace_back(
108 std::move(const_cast<DelayedTask&>(delayed_tasks_.top())));
109 delayed_tasks_.pop();
110 }
111 }
112
113 // Post delayed tasks that are ready for execution.
114 for (auto& delayed_task : ready_tasks) {
115 PostTaskNowHelper(std::move(delayed_task.task),
116 std::move(delayed_task.sequence),
117 delayed_task.priority_queue);
118 }
119 }
120
121 TimeTicks DelayedTaskManager::GetNextDelayedRunTime() const {
122 AutoSchedulerLock auto_lock(lock_);
123
124 if (delayed_tasks_.empty())
125 return TimeTicks();
126
127 return delayed_tasks_.top().task->delayed_run_time;
128 }
129
130 // In std::priority_queue, the largest element is on top. Therefore, this
131 // comparator returns true if the delayed run time of |right| is earlier than
132 // the delayed run time of |left|.
133 bool DelayedTaskManager::DelayedTaskComparator::operator()(
134 const DelayedTask& left,
135 const DelayedTask& right) const {
136 #ifndef NDEBUG
137 // Due to STL consistency checks in Windows and const_cast'ing right before
138 // popping the DelayedTask, a null task can be passed to this comparator in
139 // Debug builds. To satisfy these consistency checks, this comparator
140 // considers null tasks to be the larger than anything.
141 DCHECK(left.task || right.task);
142 if (!left.task)
143 return false;
144 if (!right.task)
145 return true;
146 #else
147 DCHECK(left.task);
148 DCHECK(right.task);
149 #endif // NDEBUG
150 if (left.task->delayed_run_time > right.task->delayed_run_time)
151 return true;
152 if (left.task->delayed_run_time < right.task->delayed_run_time)
153 return false;
154 return left.index > right.index;
155 }
156
157 TimeTicks DelayedTaskManager::Now() const {
158 return TimeTicks::Now();
159 }
160
161 } // namespace internal
162 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698