OLD | NEW |
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 #include "components/scheduler/base/task_queue_impl.h" | 5 #include "components/scheduler/base/task_queue_impl.h" |
6 | 6 |
7 #include "components/scheduler/base/task_queue_manager.h" | 7 #include "components/scheduler/base/task_queue_manager.h" |
8 #include "components/scheduler/base/task_queue_manager_delegate.h" | 8 #include "components/scheduler/base/task_queue_manager_delegate.h" |
9 #include "components/scheduler/base/time_domain.h" | 9 #include "components/scheduler/base/time_domain.h" |
10 | 10 |
11 namespace scheduler { | 11 namespace scheduler { |
12 namespace internal { | 12 namespace internal { |
13 | 13 |
14 TaskQueueImpl::TaskQueueImpl( | 14 TaskQueueImpl::TaskQueueImpl( |
15 TaskQueueManager* task_queue_manager, | 15 TaskQueueManager* task_queue_manager, |
16 TimeDomain* time_domain, | 16 const scoped_refptr<TimeDomain>& time_domain, |
17 const Spec& spec, | 17 const Spec& spec, |
18 const char* disabled_by_default_tracing_category, | 18 const char* disabled_by_default_tracing_category, |
19 const char* disabled_by_default_verbose_tracing_category) | 19 const char* disabled_by_default_verbose_tracing_category) |
20 : thread_id_(base::PlatformThread::CurrentId()), | 20 : thread_id_(base::PlatformThread::CurrentId()), |
21 any_thread_(task_queue_manager, spec.pump_policy, time_domain), | 21 any_thread_(task_queue_manager, spec.pump_policy, time_domain), |
22 name_(spec.name), | 22 name_(spec.name), |
23 disabled_by_default_tracing_category_( | 23 disabled_by_default_tracing_category_( |
24 disabled_by_default_tracing_category), | 24 disabled_by_default_tracing_category), |
25 disabled_by_default_verbose_tracing_category_( | 25 disabled_by_default_verbose_tracing_category_( |
26 disabled_by_default_verbose_tracing_category), | 26 disabled_by_default_verbose_tracing_category), |
27 main_thread_only_(task_queue_manager), | 27 main_thread_only_(task_queue_manager), |
28 wakeup_policy_(spec.wakeup_policy), | 28 wakeup_policy_(spec.wakeup_policy), |
29 should_monitor_quiescence_(spec.should_monitor_quiescence), | 29 should_monitor_quiescence_(spec.should_monitor_quiescence), |
30 should_notify_observers_(spec.should_notify_observers) { | 30 should_notify_observers_(spec.should_notify_observers) { |
31 DCHECK(time_domain); | 31 DCHECK(time_domain.get()); |
32 time_domain->RegisterQueue(this); | |
33 } | 32 } |
34 | 33 |
35 TaskQueueImpl::~TaskQueueImpl() { | 34 TaskQueueImpl::~TaskQueueImpl() {} |
36 base::AutoLock lock(any_thread_lock_); | |
37 if (any_thread().time_domain) | |
38 any_thread().time_domain->UnregisterQueue(this); | |
39 } | |
40 | 35 |
41 TaskQueueImpl::Task::Task() | 36 TaskQueueImpl::Task::Task() |
42 : PendingTask(tracked_objects::Location(), | 37 : PendingTask(tracked_objects::Location(), |
43 base::Closure(), | 38 base::Closure(), |
44 base::TimeTicks(), | 39 base::TimeTicks(), |
45 true), | 40 true), |
46 #ifndef NDEBUG | 41 #ifndef NDEBUG |
47 enqueue_order_set_(false), | 42 enqueue_order_set_(false), |
48 #endif | 43 #endif |
49 enqueue_order_(0) { | 44 enqueue_order_(0) { |
50 sequence_num = 0; | 45 sequence_num = 0; |
51 } | 46 } |
52 | 47 |
53 TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from, | 48 TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from, |
54 const base::Closure& task, | 49 const base::Closure& task, |
55 int sequence_number, | 50 int sequence_number, |
56 bool nestable) | 51 bool nestable) |
57 : PendingTask(posted_from, task, base::TimeTicks(), nestable), | 52 : PendingTask(posted_from, task, base::TimeTicks(), nestable), |
58 #ifndef NDEBUG | 53 #ifndef NDEBUG |
59 enqueue_order_set_(false), | 54 enqueue_order_set_(false), |
60 #endif | 55 #endif |
61 enqueue_order_(0) { | 56 enqueue_order_(0) { |
62 sequence_num = sequence_number; | 57 sequence_num = sequence_number; |
63 } | 58 } |
64 | 59 |
65 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, | 60 TaskQueueImpl::AnyThread::AnyThread( |
66 PumpPolicy pump_policy, | 61 TaskQueueManager* task_queue_manager, |
67 TimeDomain* time_domain) | 62 PumpPolicy pump_policy, |
| 63 const scoped_refptr<TimeDomain>& time_domain) |
68 : task_queue_manager(task_queue_manager), | 64 : task_queue_manager(task_queue_manager), |
69 pump_policy(pump_policy), | 65 pump_policy(pump_policy), |
70 time_domain(time_domain) {} | 66 time_domain(time_domain) {} |
71 | 67 |
72 TaskQueueImpl::AnyThread::~AnyThread() {} | 68 TaskQueueImpl::AnyThread::~AnyThread() {} |
73 | 69 |
74 TaskQueueImpl::MainThreadOnly::MainThreadOnly( | 70 TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
75 TaskQueueManager* task_queue_manager) | 71 TaskQueueManager* task_queue_manager) |
76 : task_queue_manager(task_queue_manager), | 72 : task_queue_manager(task_queue_manager), |
77 set_index(0) {} | 73 set_index(0) {} |
78 | 74 |
79 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 75 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
80 | 76 |
81 void TaskQueueImpl::UnregisterTaskQueue() { | 77 void TaskQueueImpl::UnregisterTaskQueue() { |
82 base::AutoLock lock(any_thread_lock_); | 78 base::AutoLock lock(any_thread_lock_); |
83 if (!any_thread().task_queue_manager) | 79 if (!any_thread().task_queue_manager) |
84 return; | 80 return; |
85 if (any_thread().time_domain) | 81 any_thread().time_domain->UnregisterQueue(this); |
86 any_thread().time_domain->UnregisterQueue(this); | |
87 any_thread().time_domain = nullptr; | 82 any_thread().time_domain = nullptr; |
88 any_thread().task_queue_manager->UnregisterTaskQueue(this); | 83 any_thread().task_queue_manager->UnregisterTaskQueue(this); |
89 | 84 |
90 any_thread().task_queue_manager = nullptr; | 85 any_thread().task_queue_manager = nullptr; |
91 main_thread_only().task_queue_manager = nullptr; | 86 main_thread_only().task_queue_manager = nullptr; |
92 any_thread().delayed_task_queue = std::priority_queue<Task>(); | 87 any_thread().delayed_task_queue = std::priority_queue<Task>(); |
93 any_thread().incoming_queue = std::queue<Task>(); | 88 any_thread().incoming_queue = std::queue<Task>(); |
94 main_thread_only().work_queue = std::queue<Task>(); | 89 main_thread_only().work_queue = std::queue<Task>(); |
95 } | 90 } |
96 | 91 |
97 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { | 92 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { |
98 base::AutoLock lock(any_thread_lock_); | 93 base::AutoLock lock(any_thread_lock_); |
99 return base::PlatformThread::CurrentId() == thread_id_; | 94 return base::PlatformThread::CurrentId() == thread_id_; |
100 } | 95 } |
101 | 96 |
102 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, | 97 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, |
103 const base::Closure& task, | 98 const base::Closure& task, |
104 base::TimeDelta delay) { | 99 base::TimeDelta delay) { |
105 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); | 100 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); |
106 } | 101 } |
107 | 102 |
108 bool TaskQueueImpl::PostNonNestableDelayedTask( | 103 bool TaskQueueImpl::PostNonNestableDelayedTask( |
109 const tracked_objects::Location& from_here, | 104 const tracked_objects::Location& from_here, |
110 const base::Closure& task, | 105 const base::Closure& task, |
111 base::TimeDelta delay) { | 106 base::TimeDelta delay) { |
112 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); | 107 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); |
113 } | 108 } |
114 | 109 |
| 110 bool TaskQueueImpl::PostDelayedTaskAt( |
| 111 const tracked_objects::Location& from_here, |
| 112 const base::Closure& task, |
| 113 base::TimeTicks desired_run_time) { |
| 114 base::AutoLock lock(any_thread_lock_); |
| 115 if (!any_thread().task_queue_manager) |
| 116 return false; |
| 117 LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); |
| 118 return PostDelayedTaskLocked(&lazy_now, from_here, task, desired_run_time, |
| 119 TaskType::NORMAL); |
| 120 } |
| 121 |
115 bool TaskQueueImpl::PostDelayedTaskImpl( | 122 bool TaskQueueImpl::PostDelayedTaskImpl( |
116 const tracked_objects::Location& from_here, | 123 const tracked_objects::Location& from_here, |
117 const base::Closure& task, | 124 const base::Closure& task, |
118 base::TimeDelta delay, | 125 base::TimeDelta delay, |
119 TaskType task_type) { | 126 TaskType task_type) { |
120 base::AutoLock lock(any_thread_lock_); | 127 base::AutoLock lock(any_thread_lock_); |
121 if (!any_thread().task_queue_manager) | 128 if (!any_thread().task_queue_manager) |
122 return false; | 129 return false; |
123 LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); | 130 LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); |
124 base::TimeTicks desired_run_time; | 131 base::TimeTicks desired_run_time; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 any_thread().task_queue_manager->DidQueueTask(thread_hop_task); | 169 any_thread().task_queue_manager->DidQueueTask(thread_hop_task); |
163 EnqueueTaskLocked(thread_hop_task); | 170 EnqueueTaskLocked(thread_hop_task); |
164 } | 171 } |
165 return true; | 172 return true; |
166 } | 173 } |
167 pending_task.set_enqueue_order(pending_task.sequence_num); | 174 pending_task.set_enqueue_order(pending_task.sequence_num); |
168 EnqueueTaskLocked(pending_task); | 175 EnqueueTaskLocked(pending_task); |
169 return true; | 176 return true; |
170 } | 177 } |
171 | 178 |
172 void TaskQueueImpl::ScheduleDelayedWorkTask(TimeDomain* time_domain, | 179 void TaskQueueImpl::ScheduleDelayedWorkTask( |
173 base::TimeTicks desired_run_time) { | 180 const scoped_refptr<TimeDomain> time_domain, |
| 181 base::TimeTicks desired_run_time) { |
174 DCHECK(main_thread_checker_.CalledOnValidThread()); | 182 DCHECK(main_thread_checker_.CalledOnValidThread()); |
175 LazyNow lazy_now(time_domain->CreateLazyNow()); | 183 LazyNow lazy_now(time_domain->CreateLazyNow()); |
176 time_domain->ScheduleDelayedWork(this, desired_run_time, &lazy_now); | 184 time_domain->ScheduleDelayedWork(this, desired_run_time, &lazy_now); |
177 } | 185 } |
178 | 186 |
179 void TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue(LazyNow* lazy_now) { | 187 void TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue(LazyNow* lazy_now) { |
180 base::AutoLock lock(any_thread_lock_); | 188 base::AutoLock lock(any_thread_lock_); |
181 if (!any_thread().task_queue_manager) | 189 if (!any_thread().task_queue_manager) |
182 return; | 190 return; |
183 | 191 |
(...skipping 20 matching lines...) Expand all Loading... |
204 return main_thread_only().task_queue_manager->selector_.IsQueueEnabled(this); | 212 return main_thread_only().task_queue_manager->selector_.IsQueueEnabled(this); |
205 } | 213 } |
206 | 214 |
207 TaskQueue::QueueState TaskQueueImpl::GetQueueState() const { | 215 TaskQueue::QueueState TaskQueueImpl::GetQueueState() const { |
208 if (!main_thread_only().work_queue.empty()) | 216 if (!main_thread_only().work_queue.empty()) |
209 return QueueState::HAS_WORK; | 217 return QueueState::HAS_WORK; |
210 | 218 |
211 { | 219 { |
212 base::AutoLock lock(any_thread_lock_); | 220 base::AutoLock lock(any_thread_lock_); |
213 if (any_thread().incoming_queue.empty()) { | 221 if (any_thread().incoming_queue.empty()) { |
214 if (any_thread().delayed_task_queue.empty()) | 222 return QueueState::EMPTY; |
215 return QueueState::EMPTY; | |
216 else | |
217 return QueueState::NO_IMMEDIATE_WORK; | |
218 } else { | 223 } else { |
219 return QueueState::NEEDS_PUMPING; | 224 return QueueState::NEEDS_PUMPING; |
220 } | 225 } |
221 } | 226 } |
222 } | 227 } |
| 228 |
223 bool TaskQueueImpl::TaskIsOlderThanQueuedTasks(const Task* task) { | 229 bool TaskQueueImpl::TaskIsOlderThanQueuedTasks(const Task* task) { |
224 // A null task is passed when UpdateQueue is called before any task is run. | 230 // A null task is passed when UpdateQueue is called before any task is run. |
225 // In this case we don't want to pump an after_wakeup queue, so return true | 231 // In this case we don't want to pump an after_wakeup queue, so return true |
226 // here. | 232 // here. |
227 if (!task) | 233 if (!task) |
228 return true; | 234 return true; |
229 | 235 |
230 // Return false if there are no task in the incoming queue. | 236 // Return false if there are no task in the incoming queue. |
231 if (any_thread().incoming_queue.empty()) | 237 if (any_thread().incoming_queue.empty()) |
232 return false; | 238 return false; |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 } | 498 } |
493 | 499 |
494 void TaskQueueImpl::NotifyDidProcessTask( | 500 void TaskQueueImpl::NotifyDidProcessTask( |
495 const base::PendingTask& pending_task) { | 501 const base::PendingTask& pending_task) { |
496 DCHECK(should_notify_observers_); | 502 DCHECK(should_notify_observers_); |
497 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, | 503 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, |
498 main_thread_only().task_observers, | 504 main_thread_only().task_observers, |
499 DidProcessTask(pending_task)); | 505 DidProcessTask(pending_task)); |
500 } | 506 } |
501 | 507 |
502 void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) { | 508 void TaskQueueImpl::SetTimeDomain( |
| 509 const scoped_refptr<TimeDomain>& time_domain) { |
503 base::AutoLock lock(any_thread_lock_); | 510 base::AutoLock lock(any_thread_lock_); |
504 DCHECK(main_thread_checker_.CalledOnValidThread()); | 511 DCHECK(main_thread_checker_.CalledOnValidThread()); |
505 if (time_domain == any_thread().time_domain) | 512 if (time_domain == any_thread().time_domain) |
506 return; | 513 return; |
507 | 514 |
508 if (time_domain) | 515 any_thread().time_domain->MigrateQueue(this, time_domain.get()); |
509 any_thread().time_domain->MigrateQueue(this, time_domain); | |
510 any_thread().time_domain = time_domain; | 516 any_thread().time_domain = time_domain; |
511 } | 517 } |
512 | 518 |
513 // static | 519 // static |
514 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, | 520 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, |
515 base::trace_event::TracedValue* state) { | 521 base::trace_event::TracedValue* state) { |
516 std::queue<Task> queue_copy(queue); | 522 std::queue<Task> queue_copy(queue); |
517 while (!queue_copy.empty()) { | 523 while (!queue_copy.empty()) { |
518 TaskAsValueInto(queue_copy.front(), state); | 524 TaskAsValueInto(queue_copy.front(), state); |
519 queue_copy.pop(); | 525 queue_copy.pop(); |
(...skipping 25 matching lines...) Expand all Loading... |
545 state->EndDictionary(); | 551 state->EndDictionary(); |
546 } | 552 } |
547 | 553 |
548 size_t TaskQueueImpl::IncomingQueueSizeForTest() const { | 554 size_t TaskQueueImpl::IncomingQueueSizeForTest() const { |
549 base::AutoLock lock(any_thread_lock_); | 555 base::AutoLock lock(any_thread_lock_); |
550 return any_thread().incoming_queue.size(); | 556 return any_thread().incoming_queue.size(); |
551 } | 557 } |
552 | 558 |
553 } // namespace internal | 559 } // namespace internal |
554 } // namespace scheduler | 560 } // namespace scheduler |
OLD | NEW |