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