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

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h

Issue 2319053004: [Reland] Make canceling Timers fast. (Closed)
Patch Set: Rebased Created 4 years, 3 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_ 5 #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_
6 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_ 6 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <memory> 10 #include <memory>
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 EnqueueOrder sequence_number, 71 EnqueueOrder sequence_number,
72 bool nestable); 72 bool nestable);
73 73
74 Task(const tracked_objects::Location& posted_from, 74 Task(const tracked_objects::Location& posted_from,
75 const base::Closure& task, 75 const base::Closure& task,
76 base::TimeTicks desired_run_time, 76 base::TimeTicks desired_run_time,
77 EnqueueOrder sequence_number, 77 EnqueueOrder sequence_number,
78 bool nestable, 78 bool nestable,
79 EnqueueOrder enqueue_order); 79 EnqueueOrder enqueue_order);
80 80
81 // Create a fake Task based on the handle, suitable for using as a search
82 // key.
83 static Task CreateFakeTaskFromHandle(const TaskHandle& handle);
84
85 EnqueueOrder enqueue_order() const { 81 EnqueueOrder enqueue_order() const {
86 #ifndef NDEBUG 82 #ifndef NDEBUG
87 DCHECK(enqueue_order_set_); 83 DCHECK(enqueue_order_set_);
88 #endif 84 #endif
89 return enqueue_order_; 85 return enqueue_order_;
90 } 86 }
91 87
92 void set_enqueue_order(EnqueueOrder enqueue_order) { 88 void set_enqueue_order(EnqueueOrder enqueue_order) {
93 #ifndef NDEBUG 89 #ifndef NDEBUG
94 DCHECK(!enqueue_order_set_); 90 DCHECK(!enqueue_order_set_);
95 enqueue_order_set_ = true; 91 enqueue_order_set_ = true;
96 #endif 92 #endif
97 enqueue_order_ = enqueue_order; 93 enqueue_order_ = enqueue_order;
98 } 94 }
99 95
100 #ifndef NDEBUG 96 #ifndef NDEBUG
101 bool enqueue_order_set() const { return enqueue_order_set_; } 97 bool enqueue_order_set() const { return enqueue_order_set_; }
102 #endif 98 #endif
103 99
104 using ComparatorFn = bool (*)(const Task&, const Task&);
105
106 // Tasks are ordered by |delayed_run_time| smallest first then and by
107 // |sequence_num| in case of a tie.
108 class DelayedRunTimeComparator {
109 public:
110 bool operator()(const Task& a, const Task& b) const;
111 };
112
113 // Tasks are ordered by |enqueue_order_| smallest first.
114 static bool EnqueueOrderComparatorFn(const TaskQueueImpl::Task& a,
115 const TaskQueueImpl::Task& b);
116
117 // Tasks are ordered by |delayed_run_time| smallest first then and by
118 // |sequence_num| in case of a tie.
119 static bool DelayedRunTimeComparatorFn(const TaskQueueImpl::Task& a,
120 const TaskQueueImpl::Task& b);
121
122 private: 100 private:
123 #ifndef NDEBUG 101 #ifndef NDEBUG
124 bool enqueue_order_set_; 102 bool enqueue_order_set_;
125 #endif 103 #endif
126 // Similar to sequence number, but ultimately the |enqueue_order_| is what 104 // Similar to sequence number, but ultimately the |enqueue_order_| is what
127 // the scheduler uses for task ordering. For immediate tasks |enqueue_order| 105 // the scheduler uses for task ordering. For immediate tasks |enqueue_order|
128 // is set when posted, but for delayed tasks it's not defined until they are 106 // is set when posted, but for delayed tasks it's not defined until they are
129 // enqueued on the |delayed_work_queue_|. This is because otherwise delayed 107 // enqueued on the |delayed_work_queue_|. This is because otherwise delayed
130 // tasks could run before an immediate task posted after the delayed task. 108 // tasks could run before an immediate task posted after the delayed task.
131 EnqueueOrder enqueue_order_; 109 EnqueueOrder enqueue_order_;
132 }; 110 };
133 111
134 // TaskQueue implementation. 112 // TaskQueue implementation.
135 void UnregisterTaskQueue() override; 113 void UnregisterTaskQueue() override;
136 bool RunsTasksOnCurrentThread() const override; 114 bool RunsTasksOnCurrentThread() const override;
137 bool PostDelayedTask(const tracked_objects::Location& from_here, 115 bool PostDelayedTask(const tracked_objects::Location& from_here,
138 const base::Closure& task, 116 const base::Closure& task,
139 base::TimeDelta delay) override; 117 base::TimeDelta delay) override;
140 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, 118 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
141 const base::Closure& task, 119 const base::Closure& task,
142 base::TimeDelta delay) override; 120 base::TimeDelta delay) override;
143 TaskHandle PostCancellableDelayedTask(
144 const tracked_objects::Location& from_here,
145 const base::Closure& task,
146 base::TimeDelta delay) override;
147 bool CancelTask(const TaskHandle& handle) override;
148 void SetQueueEnabled(bool enabled) override; 121 void SetQueueEnabled(bool enabled) override;
149 bool IsQueueEnabled() const override; 122 bool IsQueueEnabled() const override;
150 bool IsEmpty() const override; 123 bool IsEmpty() const override;
151 bool HasPendingImmediateWork() const override; 124 bool HasPendingImmediateWork() const override;
152 void SetQueuePriority(QueuePriority priority) override; 125 void SetQueuePriority(QueuePriority priority) override;
153 QueuePriority GetQueuePriority() const override; 126 QueuePriority GetQueuePriority() const override;
154 void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override; 127 void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override;
155 void RemoveTaskObserver( 128 void RemoveTaskObserver(
156 base::MessageLoop::TaskObserver* task_observer) override; 129 base::MessageLoop::TaskObserver* task_observer) override;
157 void SetTimeDomain(TimeDomain* time_domain) override; 130 void SetTimeDomain(TimeDomain* time_domain) override;
158 TimeDomain* GetTimeDomain() const override; 131 TimeDomain* GetTimeDomain() const override;
159 void SetBlameContext(base::trace_event::BlameContext* blame_context) override; 132 void SetBlameContext(base::trace_event::BlameContext* blame_context) override;
160 void InsertFence() override; 133 void InsertFence() override;
161 void RemoveFence() override; 134 void RemoveFence() override;
162 bool BlockedByFence() const override; 135 bool BlockedByFence() const override;
163 136
164 bool IsTaskPending(const TaskHandle& handle) const; 137 // If this returns false then future updates for this queue are not needed
165 138 // unless requested.
166 void UpdateImmediateWorkQueue(); 139 bool MaybeUpdateImmediateWorkQueues();
167 void UpdateDelayedWorkQueue(LazyNow* lazy_now);
168 140
169 const char* GetName() const override; 141 const char* GetName() const override;
170 142
171 void AsValueInto(base::trace_event::TracedValue* state) const; 143 void AsValueInto(base::trace_event::TracedValue* state) const;
172 144
173 bool GetQuiescenceMonitored() const { return should_monitor_quiescence_; } 145 bool GetQuiescenceMonitored() const { return should_monitor_quiescence_; }
174 bool GetShouldNotifyObservers() const { return should_notify_observers_; } 146 bool GetShouldNotifyObservers() const { return should_notify_observers_; }
175 147
176 void NotifyWillProcessTask(const base::PendingTask& pending_task); 148 void NotifyWillProcessTask(const base::PendingTask& pending_task);
177 void NotifyDidProcessTask(const base::PendingTask& pending_task); 149 void NotifyDidProcessTask(const base::PendingTask& pending_task);
(...skipping 14 matching lines...) Expand all
192 } 164 }
193 165
194 const WorkQueue* immediate_work_queue() const { 166 const WorkQueue* immediate_work_queue() const {
195 return main_thread_only().immediate_work_queue.get(); 167 return main_thread_only().immediate_work_queue.get();
196 } 168 }
197 169
198 bool should_report_when_execution_blocked() const { 170 bool should_report_when_execution_blocked() const {
199 return should_report_when_execution_blocked_; 171 return should_report_when_execution_blocked_;
200 } 172 }
201 173
174 // Enqueues any delayed tasks which should be run now on the
175 // |delayed_work_queue|. Must be called from the main thread.
176 void MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now);
177
202 private: 178 private:
203 friend class WorkQueue; 179 friend class WorkQueue;
204 friend class WorkQueueTest; 180 friend class WorkQueueTest;
205 181
206 // Note both DelayedRunTimeQueue and ComparatorQueue are sets for fast task
207 // cancellation. Typically queue sizes are well under 200 so the overhead of
208 // std::set vs std::priority_queue and std::queue is lost in the noise of
209 // everything else.
210 using DelayedRunTimeQueue = std::set<Task, Task::DelayedRunTimeComparator>;
211 using ComparatorQueue = std::set<Task, Task::ComparatorFn>;
212
213 enum class TaskType { 182 enum class TaskType {
214 NORMAL, 183 NORMAL,
215 NON_NESTABLE, 184 NON_NESTABLE,
216 }; 185 };
217 186
218 struct AnyThread { 187 struct AnyThread {
219 AnyThread(TaskQueueManager* task_queue_manager, 188 AnyThread(TaskQueueManager* task_queue_manager,
220 TimeDomain* time_domain); 189 TimeDomain* time_domain);
221 ~AnyThread(); 190 ~AnyThread();
222 191
223 // TaskQueueManager and TimeDomain are maintained in two copies: 192 // TaskQueueManager and TimeDomain are maintained in two copies:
224 // inside AnyThread and inside MainThreadOnly. They can be changed only from 193 // inside AnyThread and inside MainThreadOnly. They can be changed only from
225 // main thread, so it should be locked before accessing from other threads. 194 // main thread, so it should be locked before accessing from other threads.
226 TaskQueueManager* task_queue_manager; 195 TaskQueueManager* task_queue_manager;
227 TimeDomain* time_domain; 196 TimeDomain* time_domain;
228 197
229 ComparatorQueue immediate_incoming_queue; 198 std::queue<Task> immediate_incoming_queue;
230 }; 199 };
231 200
232 struct MainThreadOnly { 201 struct MainThreadOnly {
233 MainThreadOnly(TaskQueueManager* task_queue_manager, 202 MainThreadOnly(TaskQueueManager* task_queue_manager,
234 TaskQueueImpl* task_queue, 203 TaskQueueImpl* task_queue,
235 TimeDomain* time_domain); 204 TimeDomain* time_domain);
236 ~MainThreadOnly(); 205 ~MainThreadOnly();
237 206
238 // Another copy of TaskQueueManager and TimeDomain for lock-free access from 207 // Another copy of TaskQueueManager and TimeDomain for lock-free access from
239 // the main thread. See description inside struct AnyThread for details. 208 // the main thread. See description inside struct AnyThread for details.
240 TaskQueueManager* task_queue_manager; 209 TaskQueueManager* task_queue_manager;
241 TimeDomain* time_domain; 210 TimeDomain* time_domain;
242 211
243 std::unique_ptr<WorkQueue> delayed_work_queue; 212 std::unique_ptr<WorkQueue> delayed_work_queue;
244 std::unique_ptr<WorkQueue> immediate_work_queue; 213 std::unique_ptr<WorkQueue> immediate_work_queue;
245 DelayedRunTimeQueue delayed_incoming_queue; 214 std::priority_queue<Task> delayed_incoming_queue;
246 base::ObserverList<base::MessageLoop::TaskObserver> task_observers; 215 base::ObserverList<base::MessageLoop::TaskObserver> task_observers;
247 size_t set_index; 216 size_t set_index;
248 bool is_enabled; 217 bool is_enabled;
249 base::trace_event::BlameContext* blame_context; // Not owned. 218 base::trace_event::BlameContext* blame_context; // Not owned.
250 EnqueueOrder current_fence; 219 EnqueueOrder current_fence;
251 }; 220 };
252 221
253 ~TaskQueueImpl() override; 222 ~TaskQueueImpl() override;
254 223
255 bool PostImmediateTaskImpl(const tracked_objects::Location& from_here, 224 bool PostImmediateTaskImpl(const tracked_objects::Location& from_here,
256 const base::Closure& task, 225 const base::Closure& task,
257 TaskType task_type); 226 TaskType task_type);
258 bool PostDelayedTaskImpl(const tracked_objects::Location& from_here, 227 bool PostDelayedTaskImpl(const tracked_objects::Location& from_here,
259 const base::Closure& task, 228 const base::Closure& task,
260 base::TimeDelta delay, 229 base::TimeDelta delay,
261 TaskType task_type); 230 TaskType task_type);
262 231
263 // Push the task onto the |delayed_incoming_queue|. Lock-free main thread 232 // Push the task onto the |delayed_incoming_queue|. Lock-free main thread
264 // only fast path. 233 // only fast path.
265 void PushOntoDelayedIncomingQueueFromMainThread(Task pending_task, 234 void PushOntoDelayedIncomingQueueFromMainThread(Task pending_task,
266 base::TimeTicks now); 235 base::TimeTicks now);
267 236
268 // Push the task onto the |delayed_incoming_queue|. Slow path from other 237 // Push the task onto the |delayed_incoming_queue|. Slow path from other
269 // threads. 238 // threads.
270 void PushOntoDelayedIncomingQueueLocked(Task pending_task); 239 void PushOntoDelayedIncomingQueueLocked(Task pending_task);
271 240
272 void ScheduleDelayedWorkTask(Task pending_task); 241 void ScheduleDelayedWorkTask(Task pending_task);
273 242
274 // Enqueues any delayed tasks which should be run now on the
275 // |delayed_work_queue|. Must be called from the main thread.
276 void MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now);
277
278 void MoveReadyImmediateTasksToImmediateWorkQueueLocked(); 243 void MoveReadyImmediateTasksToImmediateWorkQueueLocked();
279 244
280 // Push the task onto the |immediate_incoming_queue| and for auto pumped 245 // Push the task onto the |immediate_incoming_queue| and for auto pumped
281 // queues it calls MaybePostDoWorkOnMainRunner if the Incoming queue was 246 // queues it calls MaybePostDoWorkOnMainRunner if the Incoming queue was
282 // empty. 247 // empty.
283 void PushOntoImmediateIncomingQueueLocked(Task pending_task); 248 void PushOntoImmediateIncomingQueueLocked(
249 const tracked_objects::Location& posted_from,
250 const base::Closure& task,
251 base::TimeTicks desired_run_time,
252 EnqueueOrder sequence_number,
253 bool nestable);
284 254
285 // As BlockedByFence but safe to be called while locked. 255 // As BlockedByFence but safe to be called while locked.
286 bool BlockedByFenceLocked() const; 256 bool BlockedByFenceLocked() const;
287 257
288 void TraceQueueSize(bool is_locked) const; 258 void TraceQueueSize(bool is_locked) const;
289 static void QueueAsValueInto(const ComparatorQueue& queue, 259 static void QueueAsValueInto(const std::queue<Task>& queue,
290 base::trace_event::TracedValue* state); 260 base::trace_event::TracedValue* state);
291 static void QueueAsValueInto(const DelayedRunTimeQueue& queue, 261 static void QueueAsValueInto(const std::priority_queue<Task>& queue,
292 base::trace_event::TracedValue* state); 262 base::trace_event::TracedValue* state);
293 static void TaskAsValueInto(const Task& task, 263 static void TaskAsValueInto(const Task& task,
294 base::trace_event::TracedValue* state); 264 base::trace_event::TracedValue* state);
295 265
296 const base::PlatformThreadId thread_id_; 266 const base::PlatformThreadId thread_id_;
297 267
298 mutable base::Lock any_thread_lock_; 268 mutable base::Lock any_thread_lock_;
299 AnyThread any_thread_; 269 AnyThread any_thread_;
300 struct AnyThread& any_thread() { 270 struct AnyThread& any_thread() {
301 any_thread_lock_.AssertAcquired(); 271 any_thread_lock_.AssertAcquired();
(...skipping 24 matching lines...) Expand all
326 const bool should_report_when_execution_blocked_; 296 const bool should_report_when_execution_blocked_;
327 297
328 DISALLOW_COPY_AND_ASSIGN(TaskQueueImpl); 298 DISALLOW_COPY_AND_ASSIGN(TaskQueueImpl);
329 }; 299 };
330 300
331 } // namespace internal 301 } // namespace internal
332 } // namespace scheduler 302 } // namespace scheduler
333 } // namespace blink 303 } // namespace blink
334 304
335 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_ 305 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/Timer.cpp ('k') | third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698