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

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

Issue 2258713004: Make tasks cancellable inside the blink scheduler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Various comment nits addressed Created 4 years, 4 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 10 matching lines...) Expand all
21 namespace blink { 21 namespace blink {
22 namespace scheduler { 22 namespace scheduler {
23 class LazyNow; 23 class LazyNow;
24 class TimeDomain; 24 class TimeDomain;
25 class TaskQueueManager; 25 class TaskQueueManager;
26 26
27 namespace internal { 27 namespace internal {
28 class WorkQueue; 28 class WorkQueue;
29 class WorkQueueSets; 29 class WorkQueueSets;
30 30
31 // TaskQueueImpl has four main queues:
32 //
33 // Immediate (non-delayed) tasks:
34 // immediate_incoming_queue - PostTask enqueues tasks here
35 // immediate_work_queue
36 //
37 // Delayed tasks
38 // delayed_incoming_queue - PostDelayedTask enqueues tasks here
39 // delayed_work_queue
40 //
41 // The immediate_incoming_queue can be accessed from any thread, the other
42 // queues are main-thread only. To reduce the overhead of locking,
43 // immediate_work_queue is swapped with immediate_incoming_queue when
44 // immediate_work_queue becomes empty.
45 //
46 // Delayed tasks are initially posted to delayed_incoming_queue and a wakeup
47 // is scheduled with the TimeDomain. When the delay has elapsed, the TimeDomain
48 // calls UpdateDelayedWorkQueue and ready delayed tasks are moved into the
49 // delayed_work_queue. Note the EnqueueOrder (used for ordering) for a delayed
50 // task is not set until it's moved into the delayed_work_queue.
51 //
52 // TaskQueueImpl uses the WorkQueueSets and the TaskQueueSelector to implement
53 // prioritization. Task selection is done by the TaskQueueSelector and when a
54 // queue is selected, it round-robins between the immediate_work_queue and
55 // delayed_work_queue. The reason for this is we want to make sure delayed
56 // tasks (normally the most common type) don't starve out immediate work.
31 class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue { 57 class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue {
32 public: 58 public:
33 TaskQueueImpl(TaskQueueManager* task_queue_manager, 59 TaskQueueImpl(TaskQueueManager* task_queue_manager,
34 TimeDomain* time_domain, 60 TimeDomain* time_domain,
35 const Spec& spec, 61 const Spec& spec,
36 const char* disabled_by_default_tracing_category, 62 const char* disabled_by_default_tracing_category,
37 const char* disabled_by_default_verbose_tracing_category); 63 const char* disabled_by_default_verbose_tracing_category);
38 64
39 class BLINK_PLATFORM_EXPORT Task : public base::PendingTask { 65 class BLINK_PLATFORM_EXPORT Task : public base::PendingTask {
40 public: 66 public:
41 Task(); 67 Task();
42 Task(const tracked_objects::Location& posted_from, 68 Task(const tracked_objects::Location& posted_from,
43 const base::Closure& task, 69 const base::Closure& task,
44 base::TimeTicks desired_run_time, 70 base::TimeTicks desired_run_time,
45 EnqueueOrder sequence_number, 71 EnqueueOrder sequence_number,
46 bool nestable); 72 bool nestable);
47 73
48 Task(const tracked_objects::Location& posted_from, 74 Task(const tracked_objects::Location& posted_from,
49 const base::Closure& task, 75 const base::Closure& task,
50 base::TimeTicks desired_run_time, 76 base::TimeTicks desired_run_time,
51 EnqueueOrder sequence_number, 77 EnqueueOrder sequence_number,
52 bool nestable, 78 bool nestable,
53 EnqueueOrder enqueue_order); 79 EnqueueOrder enqueue_order);
54 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
55 EnqueueOrder enqueue_order() const { 85 EnqueueOrder enqueue_order() const {
56 #ifndef NDEBUG 86 #ifndef NDEBUG
57 DCHECK(enqueue_order_set_); 87 DCHECK(enqueue_order_set_);
58 #endif 88 #endif
59 return enqueue_order_; 89 return enqueue_order_;
60 } 90 }
61 91
62 void set_enqueue_order(EnqueueOrder enqueue_order) { 92 void set_enqueue_order(EnqueueOrder enqueue_order) {
63 #ifndef NDEBUG 93 #ifndef NDEBUG
64 DCHECK(!enqueue_order_set_); 94 DCHECK(!enqueue_order_set_);
65 enqueue_order_set_ = true; 95 enqueue_order_set_ = true;
66 #endif 96 #endif
67 enqueue_order_ = enqueue_order; 97 enqueue_order_ = enqueue_order;
68 } 98 }
69 99
70 #ifndef NDEBUG 100 #ifndef NDEBUG
71 bool enqueue_order_set() const { return enqueue_order_set_; } 101 bool enqueue_order_set() const { return enqueue_order_set_; }
72 #endif 102 #endif
73 103
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
74 private: 122 private:
75 #ifndef NDEBUG 123 #ifndef NDEBUG
76 bool enqueue_order_set_; 124 bool enqueue_order_set_;
77 #endif 125 #endif
78 // Similar to sequence number, but the |enqueue_order| is set by 126 // Similar to sequence number, but ultimately the |enqueue_order_| is what
79 // EnqueueTasksLocked and is not initially defined for delayed tasks until 127 // the scheduler uses for task ordering. For immediate tasks |enqueue_order|
80 // they are enqueued on the |immediate_incoming_queue_|. 128 // 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
130 // tasks could run before an immediate task posted after the delayed task.
81 EnqueueOrder enqueue_order_; 131 EnqueueOrder enqueue_order_;
82 }; 132 };
83 133
84 // TaskQueue implementation. 134 // TaskQueue implementation.
85 void UnregisterTaskQueue() override; 135 void UnregisterTaskQueue() override;
86 bool RunsTasksOnCurrentThread() const override; 136 bool RunsTasksOnCurrentThread() const override;
87 bool PostDelayedTask(const tracked_objects::Location& from_here, 137 bool PostDelayedTask(const tracked_objects::Location& from_here,
88 const base::Closure& task, 138 const base::Closure& task,
89 base::TimeDelta delay) override; 139 base::TimeDelta delay) override;
90 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, 140 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
91 const base::Closure& task, 141 const base::Closure& task,
92 base::TimeDelta delay) override; 142 base::TimeDelta delay) override;
93 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;
94 void SetQueueEnabled(bool enabled) override; 148 void SetQueueEnabled(bool enabled) override;
95 bool IsQueueEnabled() const override; 149 bool IsQueueEnabled() const override;
96 bool IsEmpty() const override; 150 bool IsEmpty() const override;
97 bool HasPendingImmediateWork() const override; 151 bool HasPendingImmediateWork() const override;
98 bool NeedsPumping() const override; 152 bool NeedsPumping() const override;
99 void SetQueuePriority(QueuePriority priority) override; 153 void SetQueuePriority(QueuePriority priority) override;
100 QueuePriority GetQueuePriority() const override; 154 QueuePriority GetQueuePriority() const override;
101 void PumpQueue(LazyNow* lazy_now, bool may_post_dowork) override; 155 void PumpQueue(LazyNow* lazy_now, bool may_post_dowork) override;
102 void SetPumpPolicy(PumpPolicy pump_policy) override; 156 void SetPumpPolicy(PumpPolicy pump_policy) override;
103 PumpPolicy GetPumpPolicy() const override; 157 PumpPolicy GetPumpPolicy() const override;
104 void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override; 158 void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override;
105 void RemoveTaskObserver( 159 void RemoveTaskObserver(
106 base::MessageLoop::TaskObserver* task_observer) override; 160 base::MessageLoop::TaskObserver* task_observer) override;
107 void SetTimeDomain(TimeDomain* time_domain) override; 161 void SetTimeDomain(TimeDomain* time_domain) override;
108 TimeDomain* GetTimeDomain() const override; 162 TimeDomain* GetTimeDomain() const override;
109 void SetBlameContext(base::trace_event::BlameContext* blame_context) override; 163 void SetBlameContext(base::trace_event::BlameContext* blame_context) override;
110 164
165 bool IsTaskPending(const TaskHandle& handle) const;
166
111 void UpdateImmediateWorkQueue(bool should_trigger_wakeup, 167 void UpdateImmediateWorkQueue(bool should_trigger_wakeup,
112 const Task* previous_task); 168 const Task* previous_task);
113 void UpdateDelayedWorkQueue(LazyNow* lazy_now, 169 void UpdateDelayedWorkQueue(LazyNow* lazy_now,
114 bool should_trigger_wakeup, 170 bool should_trigger_wakeup,
115 const Task* previous_task); 171 const Task* previous_task);
116 172
117 WakeupPolicy wakeup_policy() const { 173 WakeupPolicy wakeup_policy() const {
118 DCHECK(main_thread_checker_.CalledOnValidThread()); 174 DCHECK(main_thread_checker_.CalledOnValidThread());
119 return wakeup_policy_; 175 return wakeup_policy_;
120 } 176 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 return main_thread_only().immediate_work_queue.get(); 211 return main_thread_only().immediate_work_queue.get();
156 } 212 }
157 213
158 bool should_report_when_execution_blocked() const { 214 bool should_report_when_execution_blocked() const {
159 return should_report_when_execution_blocked_; 215 return should_report_when_execution_blocked_;
160 } 216 }
161 217
162 private: 218 private:
163 friend class WorkQueue; 219 friend class WorkQueue;
164 220
221 // Note both DelayedRunTimeQueue and ComparatorQueue are sets for fast task
222 // cancellation. Typically queue sizes are well under 200 so the overhead of
223 // std::set vs std::priority_queue and std::queue is lost in the noise of
224 // everything else.
225 using DelayedRunTimeQueue = std::set<Task, Task::DelayedRunTimeComparator>;
226 using ComparatorQueue = std::set<Task, Task::ComparatorFn>;
227
165 enum class TaskType { 228 enum class TaskType {
166 NORMAL, 229 NORMAL,
167 NON_NESTABLE, 230 NON_NESTABLE,
168 }; 231 };
169 232
170 struct AnyThread { 233 struct AnyThread {
171 AnyThread(TaskQueueManager* task_queue_manager, 234 AnyThread(TaskQueueManager* task_queue_manager,
172 PumpPolicy pump_policy, 235 PumpPolicy pump_policy,
173 TimeDomain* time_domain); 236 TimeDomain* time_domain);
174 ~AnyThread(); 237 ~AnyThread();
175 238
176 // TaskQueueManager, PumpPolicy and TimeDomain are maintained in two copies: 239 // TaskQueueManager, PumpPolicy and TimeDomain are maintained in two copies:
177 // inside AnyThread and inside MainThreadOnly. They can be changed only from 240 // inside AnyThread and inside MainThreadOnly. They can be changed only from
178 // main thread, so it should be locked before accessing from other threads. 241 // main thread, so it should be locked before accessing from other threads.
179 TaskQueueManager* task_queue_manager; 242 TaskQueueManager* task_queue_manager;
180 PumpPolicy pump_policy; 243 PumpPolicy pump_policy;
181 TimeDomain* time_domain; 244 TimeDomain* time_domain;
182 245
183 std::queue<Task> immediate_incoming_queue; 246 ComparatorQueue immediate_incoming_queue;
184 }; 247 };
185 248
186 struct MainThreadOnly { 249 struct MainThreadOnly {
187 MainThreadOnly(TaskQueueManager* task_queue_manager, 250 MainThreadOnly(TaskQueueManager* task_queue_manager,
188 PumpPolicy pump_policy, 251 PumpPolicy pump_policy,
189 TaskQueueImpl* task_queue, 252 TaskQueueImpl* task_queue,
190 TimeDomain* time_domain); 253 TimeDomain* time_domain);
191 ~MainThreadOnly(); 254 ~MainThreadOnly();
192 255
193 // Another copy of TaskQueueManager, PumpPolicy and TimeDomain for lock-free 256 // Another copy of TaskQueueManager, PumpPolicy and TimeDomain for lock-free
194 // access from the main thread. See description inside struct AnyThread for 257 // access from the main thread. See description inside struct AnyThread for
195 // details. 258 // details.
196 TaskQueueManager* task_queue_manager; 259 TaskQueueManager* task_queue_manager;
197 PumpPolicy pump_policy; 260 PumpPolicy pump_policy;
198 TimeDomain* time_domain; 261 TimeDomain* time_domain;
199 262
200 std::unique_ptr<WorkQueue> delayed_work_queue; 263 std::unique_ptr<WorkQueue> delayed_work_queue;
201 std::unique_ptr<WorkQueue> immediate_work_queue; 264 std::unique_ptr<WorkQueue> immediate_work_queue;
202 std::priority_queue<Task> delayed_incoming_queue; 265 DelayedRunTimeQueue delayed_incoming_queue;
203 base::ObserverList<base::MessageLoop::TaskObserver> task_observers; 266 base::ObserverList<base::MessageLoop::TaskObserver> task_observers;
204 size_t set_index; 267 size_t set_index;
205 bool is_enabled; 268 bool is_enabled;
206 base::trace_event::BlameContext* blame_context; // Not owned. 269 base::trace_event::BlameContext* blame_context; // Not owned.
207 }; 270 };
208 271
209 ~TaskQueueImpl() override; 272 ~TaskQueueImpl() override;
210 273
211 bool PostImmediateTaskImpl(const tracked_objects::Location& from_here, 274 bool PostImmediateTaskImpl(const tracked_objects::Location& from_here,
212 const base::Closure& task, 275 const base::Closure& task,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 // Must be called from the main thread. 314 // Must be called from the main thread.
252 bool ShouldAutoPumpDelayedQueue(bool should_trigger_wakeup, 315 bool ShouldAutoPumpDelayedQueue(bool should_trigger_wakeup,
253 const Task* previous_task); 316 const Task* previous_task);
254 317
255 // Push the task onto the |immediate_incoming_queue| and for auto pumped 318 // Push the task onto the |immediate_incoming_queue| and for auto pumped
256 // queues it calls MaybePostDoWorkOnMainRunner if the Incoming queue was 319 // queues it calls MaybePostDoWorkOnMainRunner if the Incoming queue was
257 // empty. 320 // empty.
258 void PushOntoImmediateIncomingQueueLocked(Task pending_task); 321 void PushOntoImmediateIncomingQueueLocked(Task pending_task);
259 322
260 void TraceQueueSize(bool is_locked) const; 323 void TraceQueueSize(bool is_locked) const;
261 static void QueueAsValueInto(const std::queue<Task>& queue, 324 static void QueueAsValueInto(const ComparatorQueue& queue,
262 base::trace_event::TracedValue* state); 325 base::trace_event::TracedValue* state);
263 static void QueueAsValueInto(const std::priority_queue<Task>& queue, 326 static void QueueAsValueInto(const DelayedRunTimeQueue& queue,
264 base::trace_event::TracedValue* state); 327 base::trace_event::TracedValue* state);
265 static void TaskAsValueInto(const Task& task, 328 static void TaskAsValueInto(const Task& task,
266 base::trace_event::TracedValue* state); 329 base::trace_event::TracedValue* state);
267 330
268 const base::PlatformThreadId thread_id_; 331 const base::PlatformThreadId thread_id_;
269 332
270 mutable base::Lock any_thread_lock_; 333 mutable base::Lock any_thread_lock_;
271 AnyThread any_thread_; 334 AnyThread any_thread_;
272 struct AnyThread& any_thread() { 335 struct AnyThread& any_thread() {
273 any_thread_lock_.AssertAcquired(); 336 any_thread_lock_.AssertAcquired();
(...skipping 25 matching lines...) Expand all
299 const bool should_report_when_execution_blocked_; 362 const bool should_report_when_execution_blocked_;
300 363
301 DISALLOW_COPY_AND_ASSIGN(TaskQueueImpl); 364 DISALLOW_COPY_AND_ASSIGN(TaskQueueImpl);
302 }; 365 };
303 366
304 } // namespace internal 367 } // namespace internal
305 } // namespace scheduler 368 } // namespace scheduler
306 } // namespace blink 369 } // namespace blink
307 370
308 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_ 371 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698