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

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc

Issue 2546423002: [Try # 3] Scheduler refactoring to virtually eliminate redundant DoWorks (Closed)
Patch Set: Rebase it's even smaller now! Created 3 years, 10 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 #include "platform/scheduler/base/task_queue_manager.h" 5 #include "platform/scheduler/base/task_queue_manager.h"
6 6
7 #include <queue> 7 #include <queue>
8 #include <set> 8 #include <set>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 disabled_by_default_verbose_tracing_category), 68 disabled_by_default_verbose_tracing_category),
69 currently_executing_task_queue_(nullptr), 69 currently_executing_task_queue_(nullptr),
70 observer_(nullptr), 70 observer_(nullptr),
71 deletion_sentinel_(new DeletionSentinel()), 71 deletion_sentinel_(new DeletionSentinel()),
72 weak_factory_(this) { 72 weak_factory_(this) {
73 DCHECK(delegate->RunsTasksOnCurrentThread()); 73 DCHECK(delegate->RunsTasksOnCurrentThread());
74 TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category, 74 TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category,
75 "TaskQueueManager", this); 75 "TaskQueueManager", this);
76 selector_.SetTaskQueueSelectorObserver(this); 76 selector_.SetTaskQueueSelectorObserver(this);
77 77
78 from_main_thread_immediate_do_work_closure_ = 78 delayed_do_work_closure_ =
79 base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), 79 base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), true);
80 base::TimeTicks(), true); 80 immediate_do_work_closure_ =
81 from_other_thread_immediate_do_work_closure_ = 81 base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), false);
82 base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(),
83 base::TimeTicks(), false);
84 82
85 // TODO(alexclarke): Change this to be a parameter that's passed in. 83 // TODO(alexclarke): Change this to be a parameter that's passed in.
86 RegisterTimeDomain(real_time_domain_.get()); 84 RegisterTimeDomain(real_time_domain_.get());
87 85
88 delegate_->AddNestingObserver(this); 86 delegate_->AddNestingObserver(this);
89 } 87 }
90 88
91 TaskQueueManager::~TaskQueueManager() { 89 TaskQueueManager::~TaskQueueManager() {
92 TRACE_EVENT_OBJECT_DELETED_WITH_ID(disabled_by_default_tracing_category_, 90 TRACE_EVENT_OBJECT_DELETED_WITH_ID(disabled_by_default_tracing_category_,
93 "TaskQueueManager", this); 91 "TaskQueueManager", this);
94 92
95 while (!queues_.empty()) 93 while (!queues_.empty())
96 (*queues_.begin())->UnregisterTaskQueue(); 94 (*queues_.begin())->UnregisterTaskQueue();
97 95
98 selector_.SetTaskQueueSelectorObserver(nullptr); 96 selector_.SetTaskQueueSelectorObserver(nullptr);
99 97
100 delegate_->RemoveNestingObserver(this); 98 delegate_->RemoveNestingObserver(this);
101 } 99 }
102 100
103 TaskQueueManager::AnyThread::AnyThread() : other_thread_pending_wakeup(false) {} 101 TaskQueueManager::AnyThread::AnyThread()
102 : do_work_running_count(0),
103 immediate_do_work_posted_count(0),
104 is_nested(false) {}
104 105
105 void TaskQueueManager::RegisterTimeDomain(TimeDomain* time_domain) { 106 void TaskQueueManager::RegisterTimeDomain(TimeDomain* time_domain) {
106 time_domains_.insert(time_domain); 107 time_domains_.insert(time_domain);
107 time_domain->OnRegisterWithTaskQueueManager(this); 108 time_domain->OnRegisterWithTaskQueueManager(this);
108 } 109 }
109 110
110 void TaskQueueManager::UnregisterTimeDomain(TimeDomain* time_domain) { 111 void TaskQueueManager::UnregisterTimeDomain(TimeDomain* time_domain) {
111 time_domains_.erase(time_domain); 112 time_domains_.erase(time_domain);
112 } 113 }
113 114
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 } else { 177 } else {
177 LazyNow time_domain_lazy_now = time_domain->CreateLazyNow(); 178 LazyNow time_domain_lazy_now = time_domain->CreateLazyNow();
178 time_domain->WakeupReadyDelayedQueues(&time_domain_lazy_now); 179 time_domain->WakeupReadyDelayedQueues(&time_domain_lazy_now);
179 } 180 }
180 } 181 }
181 } 182 }
182 183
183 void TaskQueueManager::OnBeginNestedMessageLoop() { 184 void TaskQueueManager::OnBeginNestedMessageLoop() {
184 // We just entered a nested message loop, make sure there's a DoWork posted or 185 // We just entered a nested message loop, make sure there's a DoWork posted or
185 // the system will grind to a halt. 186 // the system will grind to a halt.
186 delegate_->PostTask(FROM_HERE, from_main_thread_immediate_do_work_closure_); 187 {
188 base::AutoLock lock(any_thread_lock_);
189 any_thread().immediate_do_work_posted_count++;
190 any_thread().is_nested = true;
191 }
192 delegate_->PostTask(FROM_HERE, immediate_do_work_closure_);
187 } 193 }
188 194
189 void TaskQueueManager::OnQueueHasIncomingImmediateWork( 195 void TaskQueueManager::OnQueueHasIncomingImmediateWork(
190 internal::TaskQueueImpl* queue, 196 internal::TaskQueueImpl* queue,
191 bool queue_is_blocked) { 197 bool queue_is_blocked) {
192 bool on_main_thread = delegate_->BelongsToCurrentThread(); 198 MoveableAutoLock lock(any_thread_lock_);
193 199 any_thread().has_incoming_immediate_work.insert(queue);
194 { 200 if (!queue_is_blocked)
195 base::AutoLock lock(any_thread_lock_); 201 MaybeScheduleImmediateWorkLocked(FROM_HERE, std::move(lock));
196 any_thread().has_incoming_immediate_work.insert(queue);
197
198 if (queue_is_blocked)
199 return;
200
201 // De-duplicate DoWork posts.
202 if (on_main_thread) {
203 if (!main_thread_pending_wakeups_.insert(base::TimeTicks()).second)
204 return;
205 } else {
206 if (any_thread().other_thread_pending_wakeup)
207 return;
208 any_thread().other_thread_pending_wakeup = true;
209 }
210 }
211
212 if (on_main_thread) {
213 delegate_->PostTask(FROM_HERE, from_main_thread_immediate_do_work_closure_);
214 } else {
215 delegate_->PostTask(FROM_HERE,
216 from_other_thread_immediate_do_work_closure_);
217 }
218 } 202 }
219 203
220 void TaskQueueManager::MaybeScheduleImmediateWork( 204 void TaskQueueManager::MaybeScheduleImmediateWork(
221 const tracked_objects::Location& from_here) { 205 const tracked_objects::Location& from_here) {
222 bool on_main_thread = delegate_->BelongsToCurrentThread(); 206 MoveableAutoLock lock(any_thread_lock_);
223 // De-duplicate DoWork posts. 207 MaybeScheduleImmediateWorkLocked(from_here, std::move(lock));
224 if (on_main_thread) { 208 }
225 if (!main_thread_pending_wakeups_.insert(base::TimeTicks()).second) { 209
210 void TaskQueueManager::MaybeScheduleImmediateWorkLocked(
211 const tracked_objects::Location& from_here,
212 MoveableAutoLock&& lock) {
213 {
214 MoveableAutoLock auto_lock(std::move(lock));
215 // Unless we're nested, try to avoid posting redundant DoWorks.
216 if (!any_thread().is_nested &&
217 (any_thread().do_work_running_count == 1 ||
218 any_thread().immediate_do_work_posted_count > 0)) {
226 return; 219 return;
Sami 2017/01/26 12:29:17 Could we DCHECK here that ComputeDelayTillNextTask
alex clarke (OOO till 29th) 2017/01/26 15:22:38 Unfortunately ComputeDelayTillNextTaskLocked has s
227 } 220 }
228 delegate_->PostTask(from_here, from_main_thread_immediate_do_work_closure_); 221
229 } else { 222 any_thread().immediate_do_work_posted_count++;
230 {
231 base::AutoLock lock(any_thread_lock_);
232 if (any_thread().other_thread_pending_wakeup)
233 return;
234 any_thread().other_thread_pending_wakeup = true;
235 }
236 delegate_->PostTask(from_here,
237 from_other_thread_immediate_do_work_closure_);
238 } 223 }
224
225 TRACE_EVENT0(disabled_by_default_tracing_category_,
226 "TaskQueueManager::MaybeScheduleImmediateWorkLocked::PostTask");
227 delegate_->PostTask(from_here, immediate_do_work_closure_);
239 } 228 }
240 229
241 void TaskQueueManager::MaybeScheduleDelayedWork( 230 void TaskQueueManager::MaybeScheduleDelayedWork(
242 const tracked_objects::Location& from_here, 231 const tracked_objects::Location& from_here,
243 base::TimeTicks now, 232 base::TimeTicks now,
244 base::TimeDelta delay) { 233 base::TimeDelta delay) {
245 DCHECK(main_thread_checker_.CalledOnValidThread()); 234 DCHECK(main_thread_checker_.CalledOnValidThread());
246 DCHECK_GE(delay, base::TimeDelta()); 235 DCHECK_GE(delay, base::TimeDelta());
236 {
237 base::AutoLock lock(any_thread_lock_);
247 238
248 // If there's a pending immediate DoWork then we rely on 239 // Unless we're nested, don't post a delayed DoWork if there's an immediate
249 // TryAdvanceTimeDomains getting the TimeDomain to call 240 // DoWork in flight or we're inside a DoWork. We can rely on DoWork posting
250 // MaybeScheduleDelayedWork again when the immediate DoWork is complete. 241 // a delayed continuation as needed.
251 if (main_thread_pending_wakeups_.find(base::TimeTicks()) != 242 if (!any_thread().is_nested &&
252 main_thread_pending_wakeups_.end()) { 243 (any_thread().immediate_do_work_posted_count > 0 ||
253 return; 244 any_thread().do_work_running_count == 1)) {
245 return;
Sami 2017/01/26 12:29:17 Similarly a DCHECK that verifies the continuation
alex clarke (OOO till 29th) 2017/01/26 15:22:38 Same problem here.
246 }
254 } 247 }
248
255 // De-duplicate DoWork posts. 249 // De-duplicate DoWork posts.
256 base::TimeTicks run_time = now + delay; 250 base::TimeTicks run_time = now + delay;
257 if (!main_thread_pending_wakeups_.empty() && 251 if (next_delayed_do_work_ <= run_time && !next_delayed_do_work_.is_null())
258 *main_thread_pending_wakeups_.begin() <= run_time) {
259 return; 252 return;
260 } 253
261 main_thread_pending_wakeups_.insert(run_time); 254 TRACE_EVENT1(disabled_by_default_tracing_category_,
255 "TaskQueueManager::MaybeScheduleDelayedWork::PostDelayedTask",
256 "delay_ms", delay.InMillisecondsF());
257
258 cancelable_delayed_do_work_closure_.Reset(delayed_do_work_closure_);
259 next_delayed_do_work_ = run_time;
262 delegate_->PostDelayedTask( 260 delegate_->PostDelayedTask(
263 from_here, base::Bind(&TaskQueueManager::DoWork, 261 from_here, cancelable_delayed_do_work_closure_.callback(), delay);
264 weak_factory_.GetWeakPtr(), run_time, true),
265 delay);
266 } 262 }
267 263
268 void TaskQueueManager::DoWork(base::TimeTicks run_time, bool from_main_thread) { 264 void TaskQueueManager::DoWork(bool delayed) {
269 DCHECK(main_thread_checker_.CalledOnValidThread()); 265 DCHECK(main_thread_checker_.CalledOnValidThread());
270 TRACE_EVENT1(tracing_category_, "TaskQueueManager::DoWork", 266 TRACE_EVENT1(tracing_category_, "TaskQueueManager::DoWork", "delayed",
271 "from_main_thread", from_main_thread); 267 delayed);
272 268
273 if (from_main_thread) { 269 LazyNow lazy_now(real_time_domain()->CreateLazyNow());
274 main_thread_pending_wakeups_.erase(run_time);
275 } else {
276 base::AutoLock lock(any_thread_lock_);
277 any_thread().other_thread_pending_wakeup = false;
278 }
279
280 // Posting a DoWork while a DoWork is running leads to spurious DoWorks.
281 main_thread_pending_wakeups_.insert(base::TimeTicks());
282
283 bool is_nested = delegate_->IsNested(); 270 bool is_nested = delegate_->IsNested();
284 if (!is_nested) 271 if (!is_nested)
285 queues_to_delete_.clear(); 272 queues_to_delete_.clear();
286 273
287 LazyNow lazy_now(real_time_domain()->CreateLazyNow()); 274 // This must be done before running any tasks because they could invoke a
288 WakeupReadyDelayedQueues(&lazy_now); 275 // nested message loop and we risk having a stale |next_delayed_do_work_|.
276 if (delayed)
277 next_delayed_do_work_ = base::TimeTicks();
289 278
290 for (int i = 0; i < work_batch_size_; i++) { 279 for (int i = 0; i < work_batch_size_; i++) {
291 std::unordered_set<internal::TaskQueueImpl*> queues_to_reload; 280 std::unordered_set<internal::TaskQueueImpl*> queues_to_reload;
292 281
293 { 282 {
294 base::AutoLock lock(any_thread_lock_); 283 base::AutoLock lock(any_thread_lock_);
284 any_thread().is_nested = is_nested;
Sami 2017/01/26 12:29:17 If I understood right, we only need to update this
alex clarke (OOO till 29th) 2017/01/26 15:22:37 Done.
285 DCHECK_EQ(any_thread().is_nested, delegate_->IsNested());
286
287 if (i == 0) {
288 any_thread().do_work_running_count++;
289
290 if (!delayed) {
291 any_thread().immediate_do_work_posted_count--;
292 DCHECK_GE(any_thread().immediate_do_work_posted_count, 0);
293 }
294 }
295 std::swap(queues_to_reload, any_thread().has_incoming_immediate_work); 295 std::swap(queues_to_reload, any_thread().has_incoming_immediate_work);
296 } 296 }
297 297
298 // It's important we call ReloadEmptyWorkQueues out side of the lock to 298 // It's important we call ReloadEmptyWorkQueues out side of the lock to
299 // avoid a lock order inversion. 299 // avoid a lock order inversion.
300 ReloadEmptyWorkQueues(queues_to_reload); 300 ReloadEmptyWorkQueues(queues_to_reload);
301 301
302 internal::WorkQueue* work_queue; 302 WakeupReadyDelayedQueues(&lazy_now);
303
304 internal::WorkQueue* work_queue = nullptr;
303 if (!SelectWorkQueueToService(&work_queue)) 305 if (!SelectWorkQueueToService(&work_queue))
304 break; 306 break;
305 307
308 // NB this may unregister |work_queue|.
306 base::TimeTicks time_after_task; 309 base::TimeTicks time_after_task;
307 switch (ProcessTaskFromWorkQueue(work_queue, is_nested, lazy_now, 310 switch (ProcessTaskFromWorkQueue(work_queue, is_nested, lazy_now,
308 &time_after_task)) { 311 &time_after_task)) {
309 case ProcessTaskResult::DEFERRED: 312 case ProcessTaskResult::DEFERRED:
310 // If a task was deferred, try again with another task. 313 // If a task was deferred, try again with another task.
311 continue; 314 continue;
312 case ProcessTaskResult::EXECUTED: 315 case ProcessTaskResult::EXECUTED:
313 break; 316 break;
314 case ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED: 317 case ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED:
315 return; // The TaskQueueManager got deleted, we must bail out. 318 return; // The TaskQueueManager got deleted, we must bail out.
316 } 319 }
317 320
318 work_queue = nullptr; // The queue may have been unregistered.
319
320 lazy_now = time_after_task.is_null() ? real_time_domain()->CreateLazyNow() 321 lazy_now = time_after_task.is_null() ? real_time_domain()->CreateLazyNow()
321 : LazyNow(time_after_task); 322 : LazyNow(time_after_task);
322 WakeupReadyDelayedQueues(&lazy_now);
323 323
324 // Only run a single task per batch in nested run loops so that we can 324 // Only run a single task per batch in nested run loops so that we can
325 // properly exit the nested loop when someone calls RunLoop::Quit(). 325 // properly exit the nested loop when someone calls RunLoop::Quit().
326 if (is_nested) 326 if (is_nested)
327 break; 327 break;
328 } 328 }
329 329
330 main_thread_pending_wakeups_.erase(base::TimeTicks());
331
332 // TODO(alexclarke): Consider refactoring the above loop to terminate only 330 // TODO(alexclarke): Consider refactoring the above loop to terminate only
333 // when there's no more work left to be done, rather than posting a 331 // when there's no more work left to be done, rather than posting a
334 // continuation task. 332 // continuation task.
335 base::Optional<base::TimeDelta> next_delay =
336 ComputeDelayTillNextTask(&lazy_now);
337 333
338 if (!next_delay) 334 {
339 return; 335 MoveableAutoLock lock(any_thread_lock_);
336 base::Optional<base::TimeDelta> next_delay =
337 ComputeDelayTillNextTaskLocked(&lazy_now);
340 338
341 base::TimeDelta delay = next_delay.value(); 339 any_thread().do_work_running_count--;
342 if (delay.is_zero()) { 340 DCHECK_GE(any_thread().do_work_running_count, 0);
343 MaybeScheduleImmediateWork(FROM_HERE); 341
344 } else { 342 any_thread().is_nested = is_nested;
345 MaybeScheduleDelayedWork(FROM_HERE, lazy_now.Now(), delay); 343 DCHECK_EQ(any_thread().is_nested, delegate_->IsNested());
344
345 PostDoWorkContinuationLocked(next_delay, &lazy_now, std::move(lock));
346 } 346 }
347 } 347 }
348 348
349 base::Optional<base::TimeDelta> TaskQueueManager::ComputeDelayTillNextTask( 349 void TaskQueueManager::PostDoWorkContinuationLocked(
350 LazyNow* lazy_now) { 350 base::Optional<base::TimeDelta> next_delay,
351 LazyNow* lazy_now,
352 MoveableAutoLock&& lock) {
353 DCHECK(main_thread_checker_.CalledOnValidThread());
354 base::TimeDelta delay;
355
356 {
357 MoveableAutoLock auto_lock(std::move(lock));
358
359 // If there are no tasks left then we don't need to post a continuation.
360 if (!next_delay) {
361 // If there's a pending delayed DoWork, cancel it because it's not needed.
362 if (!next_delayed_do_work_.is_null()) {
363 next_delayed_do_work_ = base::TimeTicks();
364 cancelable_delayed_do_work_closure_.Cancel();
365 }
366 return;
367 }
368
369 // If an immediate DoWork is posted, we don't need to post a continuation.
370 if (any_thread().immediate_do_work_posted_count > 0)
371 return;
372
373 delay = next_delay.value();
374
375 // This isn't supposed to happen, but in case it does convert to
376 // non-delayed.
377 if (delay < base::TimeDelta())
378 delay = base::TimeDelta();
379
380 if (delay.is_zero()) {
381 // If a delayed DoWork is pending then we don't need to post a
382 // continuation because it should run immediately.
383 if (!next_delayed_do_work_.is_null() &&
384 next_delayed_do_work_ <= lazy_now->Now()) {
385 return;
386 }
387
388 any_thread().immediate_do_work_posted_count++;
389 } else {
390 base::TimeTicks run_time = lazy_now->Now() + delay;
391 if (next_delayed_do_work_ == run_time)
392 return;
393
394 next_delayed_do_work_ = run_time;
395 }
396 }
397
398 // We avoid holding |any_thread_lock_| while posting the task.
399 if (delay.is_zero()) {
400 delegate_->PostTask(FROM_HERE, immediate_do_work_closure_);
401 } else {
402 cancelable_delayed_do_work_closure_.Reset(delayed_do_work_closure_);
403 delegate_->PostDelayedTask(
404 FROM_HERE, cancelable_delayed_do_work_closure_.callback(), delay);
405 }
406 }
407
408 base::Optional<base::TimeDelta>
409 TaskQueueManager::ComputeDelayTillNextTaskLocked(LazyNow* lazy_now) {
351 DCHECK(main_thread_checker_.CalledOnValidThread()); 410 DCHECK(main_thread_checker_.CalledOnValidThread());
352 411
353 std::unordered_set<internal::TaskQueueImpl*> queues_to_reload; 412 // Unfortunately because |any_thread_lock_| is held it's not safe to call
Sami 2017/01/26 12:29:17 I guess we could call ReloadWorkQueues() right bef
alex clarke (OOO till 29th) 2017/01/26 15:22:38 So in theory the check now is entirely equivalent
354 { 413 // ReloadEmptyWorkQueues here (possible lock order inversion).
355 base::AutoLock lock(any_thread_lock_); 414 for (const internal::TaskQueueImpl* queue :
356 std::swap(queues_to_reload, any_thread().has_incoming_immediate_work); 415 any_thread().has_incoming_immediate_work) {
416 if (queue->IsQueueEnabled() && !queue->HasFence())
417 return base::TimeDelta();
357 } 418 }
358 419
359 // It's important we call ReloadEmptyWorkQueues out side of the lock to
360 // avoid a lock order inversion.
361 ReloadEmptyWorkQueues(queues_to_reload);
362
363 // If the selector has non-empty queues we trivially know there is immediate 420 // If the selector has non-empty queues we trivially know there is immediate
364 // work to be done. 421 // work to be done.
365 if (!selector_.EnabledWorkQueuesEmpty()) 422 if (!selector_.EnabledWorkQueuesEmpty())
366 return base::TimeDelta(); 423 return base::TimeDelta();
367 424
368 // Otherwise we need to find the shortest delay, if any. 425 // Otherwise we need to find the shortest delay, if any.
369 base::Optional<base::TimeDelta> next_continuation; 426 base::Optional<base::TimeDelta> next_continuation;
370 for (TimeDomain* time_domain : time_domains_) { 427 for (TimeDomain* time_domain : time_domains_) {
371 base::Optional<base::TimeDelta> continuation = 428 base::Optional<base::TimeDelta> continuation =
372 time_domain->DelayTillNextTask(lazy_now); 429 time_domain->DelayTillNextTask(lazy_now);
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 selected_work_queue->task_queue()->GetName()); 628 selected_work_queue->task_queue()->GetName());
572 state->SetString("work_queue_name", selected_work_queue->name()); 629 state->SetString("work_queue_name", selected_work_queue->name());
573 } 630 }
574 631
575 state->BeginArray("time_domains"); 632 state->BeginArray("time_domains");
576 for (auto* time_domain : time_domains_) 633 for (auto* time_domain : time_domains_)
577 time_domain->AsValueInto(state.get()); 634 time_domain->AsValueInto(state.get());
578 state->EndArray(); 635 state->EndArray();
579 { 636 {
580 base::AutoLock lock(any_thread_lock_); 637 base::AutoLock lock(any_thread_lock_);
638 state->SetBoolean("is_nested", any_thread().is_nested);
639 state->SetInteger("do_work_running_count",
640 any_thread().do_work_running_count);
641 state->SetInteger("immediate_do_work_posted_count",
642 any_thread().immediate_do_work_posted_count);
643
581 state->BeginArray("has_incoming_immediate_work"); 644 state->BeginArray("has_incoming_immediate_work");
582 for (internal::TaskQueueImpl* task_queue : 645 for (internal::TaskQueueImpl* task_queue :
583 any_thread().has_incoming_immediate_work) { 646 any_thread().has_incoming_immediate_work) {
584 state->AppendString(task_queue->GetName()); 647 state->AppendString(task_queue->GetName());
585 } 648 }
586 state->EndArray(); 649 state->EndArray();
587 } 650 }
588 return std::move(state); 651 return std::move(state);
589 } 652 }
590 653
(...skipping 30 matching lines...) Expand all
621 for (const scoped_refptr<internal::TaskQueueImpl>& queue : queues_) { 684 for (const scoped_refptr<internal::TaskQueueImpl>& queue : queues_) {
622 TimeDomain* time_domain = queue->GetTimeDomain(); 685 TimeDomain* time_domain = queue->GetTimeDomain();
623 if (time_domain_now.find(time_domain) == time_domain_now.end()) 686 if (time_domain_now.find(time_domain) == time_domain_now.end())
624 time_domain_now.insert(std::make_pair(time_domain, time_domain->Now())); 687 time_domain_now.insert(std::make_pair(time_domain, time_domain->Now()));
625 queue->SweepCanceledDelayedTasks(time_domain_now[time_domain]); 688 queue->SweepCanceledDelayedTasks(time_domain_now[time_domain]);
626 } 689 }
627 } 690 }
628 691
629 } // namespace scheduler 692 } // namespace scheduler
630 } // namespace blink 693 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698