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

Side by Side Diff: components/scheduler/base/task_queue_impl.cc

Issue 2118903002: scheduler: Move the Blink scheduler into Blink (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/scheduler/base/task_queue_impl.h"
6
7 #include "base/trace_event/blame_context.h"
8 #include "components/scheduler/base/task_queue_manager.h"
9 #include "components/scheduler/base/task_queue_manager_delegate.h"
10 #include "components/scheduler/base/time_domain.h"
11 #include "components/scheduler/base/work_queue.h"
12
13 namespace scheduler {
14 namespace internal {
15
16 TaskQueueImpl::TaskQueueImpl(
17 TaskQueueManager* task_queue_manager,
18 TimeDomain* time_domain,
19 const Spec& spec,
20 const char* disabled_by_default_tracing_category,
21 const char* disabled_by_default_verbose_tracing_category)
22 : thread_id_(base::PlatformThread::CurrentId()),
23 any_thread_(task_queue_manager, spec.pump_policy, time_domain),
24 name_(spec.name),
25 disabled_by_default_tracing_category_(
26 disabled_by_default_tracing_category),
27 disabled_by_default_verbose_tracing_category_(
28 disabled_by_default_verbose_tracing_category),
29 main_thread_only_(task_queue_manager,
30 spec.pump_policy,
31 this,
32 time_domain),
33 wakeup_policy_(spec.wakeup_policy),
34 should_monitor_quiescence_(spec.should_monitor_quiescence),
35 should_notify_observers_(spec.should_notify_observers),
36 should_report_when_execution_blocked_(
37 spec.should_report_when_execution_blocked) {
38 DCHECK(time_domain);
39 time_domain->RegisterQueue(this);
40 }
41
42 TaskQueueImpl::~TaskQueueImpl() {
43 #if DCHECK_IS_ON()
44 base::AutoLock lock(any_thread_lock_);
45 // NOTE this check shouldn't fire because |TaskQueueManager::queues_|
46 // contains a strong reference to this TaskQueueImpl and the TaskQueueManager
47 // destructor calls UnregisterTaskQueue on all task queues.
48 DCHECK(any_thread().task_queue_manager == nullptr)
49 << "UnregisterTaskQueue must be called first!";
50
51 #endif
52 }
53
54 TaskQueueImpl::Task::Task()
55 : PendingTask(tracked_objects::Location(),
56 base::Closure(),
57 base::TimeTicks(),
58 true),
59 #ifndef NDEBUG
60 enqueue_order_set_(false),
61 #endif
62 enqueue_order_(0) {
63 sequence_num = 0;
64 }
65
66 TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from,
67 const base::Closure& task,
68 base::TimeTicks desired_run_time,
69 EnqueueOrder sequence_number,
70 bool nestable)
71 : PendingTask(posted_from, task, desired_run_time, nestable),
72 #ifndef NDEBUG
73 enqueue_order_set_(false),
74 #endif
75 enqueue_order_(0) {
76 sequence_num = sequence_number;
77 }
78
79 TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from,
80 const base::Closure& task,
81 base::TimeTicks desired_run_time,
82 EnqueueOrder sequence_number,
83 bool nestable,
84 EnqueueOrder enqueue_order)
85 : PendingTask(posted_from, task, desired_run_time, nestable),
86 #ifndef NDEBUG
87 enqueue_order_set_(true),
88 #endif
89 enqueue_order_(enqueue_order) {
90 sequence_num = sequence_number;
91 }
92
93 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager,
94 PumpPolicy pump_policy,
95 TimeDomain* time_domain)
96 : task_queue_manager(task_queue_manager),
97 pump_policy(pump_policy),
98 time_domain(time_domain) {}
99
100 TaskQueueImpl::AnyThread::~AnyThread() {}
101
102 TaskQueueImpl::MainThreadOnly::MainThreadOnly(
103 TaskQueueManager* task_queue_manager,
104 PumpPolicy pump_policy,
105 TaskQueueImpl* task_queue,
106 TimeDomain* time_domain)
107 : task_queue_manager(task_queue_manager),
108 pump_policy(pump_policy),
109 time_domain(time_domain),
110 delayed_work_queue(new WorkQueue(task_queue, "delayed")),
111 immediate_work_queue(new WorkQueue(task_queue, "immediate")),
112 set_index(0),
113 is_enabled(true),
114 blame_context(nullptr) {}
115
116 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {}
117
118 void TaskQueueImpl::UnregisterTaskQueue() {
119 base::AutoLock lock(any_thread_lock_);
120 if (main_thread_only().time_domain)
121 main_thread_only().time_domain->UnregisterQueue(this);
122 if (!any_thread().task_queue_manager)
123 return;
124 any_thread().time_domain = nullptr;
125 main_thread_only().time_domain = nullptr;
126 any_thread().task_queue_manager->UnregisterTaskQueue(this);
127
128 any_thread().task_queue_manager = nullptr;
129 main_thread_only().task_queue_manager = nullptr;
130 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>();
131 any_thread().immediate_incoming_queue = std::queue<Task>();
132 main_thread_only().immediate_work_queue.reset();
133 main_thread_only().delayed_work_queue.reset();
134 }
135
136 bool TaskQueueImpl::RunsTasksOnCurrentThread() const {
137 base::AutoLock lock(any_thread_lock_);
138 return base::PlatformThread::CurrentId() == thread_id_;
139 }
140
141 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here,
142 const base::Closure& task,
143 base::TimeDelta delay) {
144 if (delay.is_zero())
145 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL);
146
147 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL);
148 }
149
150 bool TaskQueueImpl::PostNonNestableDelayedTask(
151 const tracked_objects::Location& from_here,
152 const base::Closure& task,
153 base::TimeDelta delay) {
154 if (delay.is_zero())
155 return PostImmediateTaskImpl(from_here, task, TaskType::NON_NESTABLE);
156
157 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE);
158 }
159
160 bool TaskQueueImpl::PostImmediateTaskImpl(
161 const tracked_objects::Location& from_here,
162 const base::Closure& task,
163 TaskType task_type) {
164 base::AutoLock lock(any_thread_lock_);
165 if (!any_thread().task_queue_manager)
166 return false;
167
168 EnqueueOrder sequence_number =
169 any_thread().task_queue_manager->GetNextSequenceNumber();
170
171 PushOntoImmediateIncomingQueueLocked(
172 Task(from_here, task, base::TimeTicks(), sequence_number,
173 task_type != TaskType::NON_NESTABLE, sequence_number));
174 return true;
175 }
176
177 bool TaskQueueImpl::PostDelayedTaskImpl(
178 const tracked_objects::Location& from_here,
179 const base::Closure& task,
180 base::TimeDelta delay,
181 TaskType task_type) {
182 DCHECK_GT(delay, base::TimeDelta());
183 if (base::PlatformThread::CurrentId() == thread_id_) {
184 // Lock-free fast path for delayed tasks posted from the main thread.
185 if (!main_thread_only().task_queue_manager)
186 return false;
187
188 EnqueueOrder sequence_number =
189 main_thread_only().task_queue_manager->GetNextSequenceNumber();
190
191 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
192 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
193 PushOntoDelayedIncomingQueueFromMainThread(
194 Task(from_here, task, time_domain_delayed_run_time, sequence_number,
195 task_type != TaskType::NON_NESTABLE),
196 time_domain_now);
197 } else {
198 // NOTE posting a delayed task from a different thread is not expected to
199 // be common. This pathway is less optimal than perhaps it could be
200 // because it causes two main thread tasks to be run. Should this
201 // assumption prove to be false in future, we may need to revisit this.
202 base::AutoLock lock(any_thread_lock_);
203 if (!any_thread().task_queue_manager)
204 return false;
205
206 EnqueueOrder sequence_number =
207 any_thread().task_queue_manager->GetNextSequenceNumber();
208
209 base::TimeTicks time_domain_now = any_thread().time_domain->Now();
210 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
211 PushOntoDelayedIncomingQueueLocked(
212 Task(from_here, task, time_domain_delayed_run_time, sequence_number,
213 task_type != TaskType::NON_NESTABLE));
214 }
215 return true;
216 }
217
218 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread(
219 Task pending_task,
220 base::TimeTicks now) {
221 main_thread_only().task_queue_manager->DidQueueTask(pending_task);
222
223 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue.
224 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
225 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
226 main_thread_only().time_domain->ScheduleDelayedWork(
227 this, delayed_run_time, now);
228 TraceQueueSize(false);
229 }
230
231 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) {
232 any_thread().task_queue_manager->DidQueueTask(pending_task);
233
234 int thread_hop_task_sequence_number =
235 any_thread().task_queue_manager->GetNextSequenceNumber();
236 PushOntoImmediateIncomingQueueLocked(Task(
237 FROM_HERE,
238 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this,
239 base::Passed(&pending_task)),
240 base::TimeTicks(), thread_hop_task_sequence_number, false,
241 thread_hop_task_sequence_number));
242 }
243
244 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) {
245 if (any_thread().immediate_incoming_queue.empty())
246 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
247 if (any_thread().pump_policy == PumpPolicy::AUTO &&
248 any_thread().immediate_incoming_queue.empty()) {
249 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
250 }
251 any_thread().task_queue_manager->DidQueueTask(pending_task);
252 any_thread().immediate_incoming_queue.push(std::move(pending_task));
253 TraceQueueSize(true);
254 }
255
256 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) {
257 DCHECK(main_thread_checker_.CalledOnValidThread());
258 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
259 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
260 main_thread_only().time_domain->ScheduleDelayedWork(
261 this, delayed_run_time,
262 main_thread_only().time_domain->Now());
263 }
264
265 void TaskQueueImpl::SetQueueEnabled(bool enabled) {
266 if (main_thread_only().is_enabled == enabled)
267 return;
268 main_thread_only().is_enabled = enabled;
269 if (!main_thread_only().task_queue_manager)
270 return;
271 if (enabled) {
272 main_thread_only().task_queue_manager->selector_.EnableQueue(this);
273 } else {
274 main_thread_only().task_queue_manager->selector_.DisableQueue(this);
275 }
276 }
277
278 bool TaskQueueImpl::IsQueueEnabled() const {
279 return main_thread_only().is_enabled;
280 }
281
282 bool TaskQueueImpl::IsEmpty() const {
283 if (!main_thread_only().delayed_work_queue->Empty() ||
284 !main_thread_only().immediate_work_queue->Empty()) {
285 return false;
286 }
287
288 base::AutoLock lock(any_thread_lock_);
289 return any_thread().immediate_incoming_queue.empty() &&
290 main_thread_only().delayed_incoming_queue.empty();
291 }
292
293 bool TaskQueueImpl::HasPendingImmediateWork() const {
294 if (!main_thread_only().delayed_work_queue->Empty() ||
295 !main_thread_only().immediate_work_queue->Empty()) {
296 return true;
297 }
298
299 return NeedsPumping();
300 }
301
302 bool TaskQueueImpl::NeedsPumping() const {
303 if (!main_thread_only().immediate_work_queue->Empty())
304 return false;
305
306 base::AutoLock lock(any_thread_lock_);
307 if (!any_thread().immediate_incoming_queue.empty())
308 return true;
309
310 // If there's no immediate Incoming work then we only need pumping if there
311 // is a delayed task that should be running now.
312 if (main_thread_only().delayed_incoming_queue.empty())
313 return false;
314
315 return main_thread_only().delayed_incoming_queue.top().delayed_run_time <=
316 main_thread_only().time_domain->CreateLazyNow().Now();
317 }
318
319 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked(
320 const Task* task) {
321 // A null task is passed when UpdateQueue is called before any task is run.
322 // In this case we don't want to pump an after_wakeup queue, so return true
323 // here.
324 if (!task)
325 return true;
326
327 // Return false if task is newer than the oldest immediate task.
328 if (!any_thread().immediate_incoming_queue.empty() &&
329 task->enqueue_order() >
330 any_thread().immediate_incoming_queue.front().enqueue_order()) {
331 return false;
332 }
333 return true;
334 }
335
336 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) {
337 DCHECK(main_thread_checker_.CalledOnValidThread());
338 // A null task is passed when UpdateQueue is called before any task is run.
339 // In this case we don't want to pump an after_wakeup queue, so return true
340 // here.
341 if (!task)
342 return true;
343
344 EnqueueOrder enqueue_order;
345 if (!main_thread_only().delayed_work_queue->GetFrontTaskEnqueueOrder(
346 &enqueue_order)) {
347 return true;
348 }
349
350 return task->enqueue_order() < enqueue_order;
351 }
352
353 bool TaskQueueImpl::ShouldAutoPumpImmediateQueueLocked(
354 bool should_trigger_wakeup,
355 const Task* previous_task) {
356 if (main_thread_only().pump_policy == PumpPolicy::MANUAL)
357 return false;
358 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP &&
359 (!should_trigger_wakeup ||
360 TaskIsOlderThanQueuedImmediateTasksLocked(previous_task)))
361 return false;
362 return true;
363 }
364
365 bool TaskQueueImpl::ShouldAutoPumpDelayedQueue(bool should_trigger_wakeup,
366 const Task* previous_task) {
367 if (main_thread_only().pump_policy == PumpPolicy::MANUAL)
368 return false;
369 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP &&
370 (!should_trigger_wakeup ||
371 TaskIsOlderThanQueuedDelayedTasks(previous_task)))
372 return false;
373 return true;
374 }
375
376 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) {
377 // Enqueue all delayed tasks that should be running now.
378 while (!main_thread_only().delayed_incoming_queue.empty() &&
379 main_thread_only().delayed_incoming_queue.top().delayed_run_time <=
380 lazy_now->Now()) {
381 // Note: the const_cast is needed because there is no direct way to move
382 // elements out of a priority queue. The queue must not be modified between
383 // the top() and the pop().
384 main_thread_only().delayed_work_queue->PushAndSetEnqueueOrder(
385 std::move(
386 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top())),
387 main_thread_only().task_queue_manager->GetNextSequenceNumber());
388 main_thread_only().delayed_incoming_queue.pop();
389 }
390 }
391
392 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now,
393 bool should_trigger_wakeup,
394 const Task* previous_task) {
395 if (!main_thread_only().task_queue_manager)
396 return;
397 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task))
398 return;
399 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now);
400 TraceQueueSize(false);
401 }
402
403 void TaskQueueImpl::UpdateImmediateWorkQueue(bool should_trigger_wakeup,
404 const Task* previous_task) {
405 DCHECK(main_thread_only().immediate_work_queue->Empty());
406 base::AutoLock lock(any_thread_lock_);
407 if (!main_thread_only().task_queue_manager)
408 return;
409 if (!ShouldAutoPumpImmediateQueueLocked(should_trigger_wakeup, previous_task))
410 return;
411
412 main_thread_only().immediate_work_queue->SwapLocked(
413 any_thread().immediate_incoming_queue);
414
415 // |any_thread().immediate_incoming_queue| is now empty so
416 // TimeDomain::UpdateQueues no longer needs to consider this queue for
417 // reloading.
418 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this);
419 }
420
421 void TaskQueueImpl::TraceQueueSize(bool is_locked) const {
422 bool is_tracing;
423 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_,
424 &is_tracing);
425 if (!is_tracing)
426 return;
427
428 // It's only safe to access the work queues from the main thread.
429 // TODO(alexclarke): We should find another way of tracing this
430 if (base::PlatformThread::CurrentId() != thread_id_)
431 return;
432
433 if (!is_locked)
434 any_thread_lock_.Acquire();
435 else
436 any_thread_lock_.AssertAcquired();
437 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(),
438 any_thread().immediate_incoming_queue.size() +
439 main_thread_only().immediate_work_queue->Size() +
440 main_thread_only().delayed_work_queue->Size() +
441 main_thread_only().delayed_incoming_queue.size());
442 if (!is_locked)
443 any_thread_lock_.Release();
444 }
445
446 void TaskQueueImpl::SetPumpPolicy(PumpPolicy pump_policy) {
447 base::AutoLock lock(any_thread_lock_);
448 if (pump_policy == PumpPolicy::AUTO &&
449 any_thread().pump_policy != PumpPolicy::AUTO) {
450 LazyNow lazy_now(main_thread_only().time_domain->CreateLazyNow());
451 PumpQueueLocked(&lazy_now, true);
452 }
453 any_thread().pump_policy = pump_policy;
454 main_thread_only().pump_policy = pump_policy;
455 }
456
457 TaskQueue::PumpPolicy TaskQueueImpl::GetPumpPolicy() const {
458 return main_thread_only().pump_policy;
459 }
460
461 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) {
462 TRACE_EVENT1(disabled_by_default_tracing_category_,
463 "TaskQueueImpl::PumpQueueLocked", "queue", name_);
464 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager;
465 if (!task_queue_manager)
466 return;
467
468 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now);
469
470 while (!any_thread().immediate_incoming_queue.empty()) {
471 main_thread_only().immediate_work_queue->Push(
472 std::move(any_thread().immediate_incoming_queue.front()));
473 any_thread().immediate_incoming_queue.pop();
474 }
475
476 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no
477 // longer needs to consider this queue for reloading.
478 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this);
479
480 if (main_thread_only().immediate_work_queue->Empty() &&
481 main_thread_only().delayed_work_queue->Empty()) {
482 return;
483 }
484
485 if (may_post_dowork)
486 task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
487 }
488
489 void TaskQueueImpl::PumpQueue(LazyNow* lazy_now, bool may_post_dowork) {
490 base::AutoLock lock(any_thread_lock_);
491 PumpQueueLocked(lazy_now, may_post_dowork);
492 }
493
494 const char* TaskQueueImpl::GetName() const {
495 return name_;
496 }
497
498 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) {
499 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority())
500 return;
501 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this,
502 priority);
503 }
504
505 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const {
506 size_t set_index = immediate_work_queue()->work_queue_set_index();
507 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index());
508 return static_cast<TaskQueue::QueuePriority>(set_index);
509 }
510
511 // static
512 const char* TaskQueueImpl::PumpPolicyToString(
513 TaskQueue::PumpPolicy pump_policy) {
514 switch (pump_policy) {
515 case TaskQueue::PumpPolicy::AUTO:
516 return "auto";
517 case TaskQueue::PumpPolicy::AFTER_WAKEUP:
518 return "after_wakeup";
519 case TaskQueue::PumpPolicy::MANUAL:
520 return "manual";
521 default:
522 NOTREACHED();
523 return nullptr;
524 }
525 }
526
527 // static
528 const char* TaskQueueImpl::WakeupPolicyToString(
529 TaskQueue::WakeupPolicy wakeup_policy) {
530 switch (wakeup_policy) {
531 case TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES:
532 return "can_wake_other_queues";
533 case TaskQueue::WakeupPolicy::DONT_WAKE_OTHER_QUEUES:
534 return "dont_wake_other_queues";
535 default:
536 NOTREACHED();
537 return nullptr;
538 }
539 }
540
541 // static
542 const char* TaskQueueImpl::PriorityToString(QueuePriority priority) {
543 switch (priority) {
544 case CONTROL_PRIORITY:
545 return "control";
546 case HIGH_PRIORITY:
547 return "high";
548 case NORMAL_PRIORITY:
549 return "normal";
550 case BEST_EFFORT_PRIORITY:
551 return "best_effort";
552 default:
553 NOTREACHED();
554 return nullptr;
555 }
556 }
557
558 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const {
559 base::AutoLock lock(any_thread_lock_);
560 state->BeginDictionary();
561 state->SetString("name", GetName());
562 state->SetBoolean("enabled", main_thread_only().is_enabled);
563 state->SetString("time_domain_name",
564 main_thread_only().time_domain->GetName());
565 state->SetString("pump_policy", PumpPolicyToString(any_thread().pump_policy));
566 state->SetString("wakeup_policy", WakeupPolicyToString(wakeup_policy_));
567 bool verbose_tracing_enabled = false;
568 TRACE_EVENT_CATEGORY_GROUP_ENABLED(
569 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled);
570 state->SetInteger("immediate_incoming_queue_size",
571 any_thread().immediate_incoming_queue.size());
572 state->SetInteger("delayed_incoming_queue_size",
573 main_thread_only().delayed_incoming_queue.size());
574 state->SetInteger("immediate_work_queue_size",
575 main_thread_only().immediate_work_queue->Size());
576 state->SetInteger("delayed_work_queue_size",
577 main_thread_only().delayed_work_queue->Size());
578 if (!main_thread_only().delayed_incoming_queue.empty()) {
579 base::TimeDelta delay_to_next_task =
580 (main_thread_only().delayed_incoming_queue.top().delayed_run_time -
581 main_thread_only().time_domain->CreateLazyNow().Now());
582 state->SetDouble("delay_to_next_task_ms",
583 delay_to_next_task.InMillisecondsF());
584 }
585 if (verbose_tracing_enabled) {
586 state->BeginArray("immediate_incoming_queue");
587 QueueAsValueInto(any_thread().immediate_incoming_queue, state);
588 state->EndArray();
589 state->BeginArray("delayed_work_queue");
590 main_thread_only().delayed_work_queue->AsValueInto(state);
591 state->EndArray();
592 state->BeginArray("immediate_work_queue");
593 main_thread_only().immediate_work_queue->AsValueInto(state);
594 state->EndArray();
595 state->BeginArray("delayed_incoming_queue");
596 QueueAsValueInto(main_thread_only().delayed_incoming_queue, state);
597 state->EndArray();
598 }
599 state->SetString("priority", PriorityToString(GetQueuePriority()));
600 state->EndDictionary();
601 }
602
603 void TaskQueueImpl::AddTaskObserver(
604 base::MessageLoop::TaskObserver* task_observer) {
605 main_thread_only().task_observers.AddObserver(task_observer);
606 }
607
608 void TaskQueueImpl::RemoveTaskObserver(
609 base::MessageLoop::TaskObserver* task_observer) {
610 main_thread_only().task_observers.RemoveObserver(task_observer);
611 }
612
613 void TaskQueueImpl::NotifyWillProcessTask(
614 const base::PendingTask& pending_task) {
615 DCHECK(should_notify_observers_);
616 if (main_thread_only().blame_context)
617 main_thread_only().blame_context->Enter();
618 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver,
619 main_thread_only().task_observers,
620 WillProcessTask(pending_task));
621 }
622
623 void TaskQueueImpl::NotifyDidProcessTask(
624 const base::PendingTask& pending_task) {
625 DCHECK(should_notify_observers_);
626 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver,
627 main_thread_only().task_observers,
628 DidProcessTask(pending_task));
629 if (main_thread_only().blame_context)
630 main_thread_only().blame_context->Leave();
631 }
632
633 void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) {
634 base::AutoLock lock(any_thread_lock_);
635 DCHECK(time_domain);
636 // NOTE this is similar to checking |any_thread().task_queue_manager| but the
637 // TaskQueueSelectorTests constructs TaskQueueImpl directly with a null
638 // task_queue_manager. Instead we check |any_thread().time_domain| which is
639 // another way of asserting that UnregisterTaskQueue has not been called.
640 DCHECK(any_thread().time_domain);
641 if (!any_thread().time_domain)
642 return;
643 DCHECK(main_thread_checker_.CalledOnValidThread());
644 if (time_domain == main_thread_only().time_domain)
645 return;
646
647 main_thread_only().time_domain->MigrateQueue(this, time_domain);
648 main_thread_only().time_domain = time_domain;
649 any_thread().time_domain = time_domain;
650 }
651
652 TimeDomain* TaskQueueImpl::GetTimeDomain() const {
653 if (base::PlatformThread::CurrentId() == thread_id_)
654 return main_thread_only().time_domain;
655
656 base::AutoLock lock(any_thread_lock_);
657 return any_thread().time_domain;
658 }
659
660 void TaskQueueImpl::SetBlameContext(
661 base::trace_event::BlameContext* blame_context) {
662 main_thread_only().blame_context = blame_context;
663 }
664
665 // static
666 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue,
667 base::trace_event::TracedValue* state) {
668 // Remove const to search |queue| in the destructive manner. Restore the
669 // content from |visited| later.
670 std::queue<Task>* mutable_queue = const_cast<std::queue<Task>*>(&queue);
671 std::queue<Task> visited;
672 while (!mutable_queue->empty()) {
673 TaskAsValueInto(mutable_queue->front(), state);
674 visited.push(std::move(mutable_queue->front()));
675 mutable_queue->pop();
676 }
677 *mutable_queue = std::move(visited);
678 }
679
680 // static
681 void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue,
682 base::trace_event::TracedValue* state) {
683 // Remove const to search |queue| in the destructive manner. Restore the
684 // content from |visited| later.
685 std::priority_queue<Task>* mutable_queue =
686 const_cast<std::priority_queue<Task>*>(&queue);
687 std::priority_queue<Task> visited;
688 while (!mutable_queue->empty()) {
689 TaskAsValueInto(mutable_queue->top(), state);
690 visited.push(std::move(const_cast<Task&>(mutable_queue->top())));
691 mutable_queue->pop();
692 }
693 *mutable_queue = std::move(visited);
694 }
695
696 // static
697 void TaskQueueImpl::TaskAsValueInto(const Task& task,
698 base::trace_event::TracedValue* state) {
699 state->BeginDictionary();
700 state->SetString("posted_from", task.posted_from.ToString());
701 #ifndef NDEBUG
702 if (task.enqueue_order_set())
703 state->SetInteger("enqueue_order", task.enqueue_order());
704 #else
705 state->SetInteger("enqueue_order", task.enqueue_order());
706 #endif
707 state->SetInteger("sequence_num", task.sequence_num);
708 state->SetBoolean("nestable", task.nestable);
709 state->SetBoolean("is_high_res", task.is_high_res);
710 state->SetDouble(
711 "delayed_run_time",
712 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L);
713 state->EndDictionary();
714 }
715
716 } // namespace internal
717 } // namespace scheduler
OLDNEW
« no previous file with comments | « components/scheduler/base/task_queue_impl.h ('k') | components/scheduler/base/task_queue_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698