• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 "base/task/sequence_manager/task_queue.h"
6 
7 #include "base/bind.h"
8 #include "base/task/sequence_manager/sequence_manager_impl.h"
9 #include "base/task/sequence_manager/task_queue_impl.h"
10 #include "base/time/time.h"
11 
12 namespace base {
13 namespace sequence_manager {
14 
TaskQueue(std::unique_ptr<internal::TaskQueueImpl> impl,const TaskQueue::Spec & spec)15 TaskQueue::TaskQueue(std::unique_ptr<internal::TaskQueueImpl> impl,
16                      const TaskQueue::Spec& spec)
17     : impl_(std::move(impl)),
18       thread_id_(PlatformThread::CurrentId()),
19       sequence_manager_(impl_ ? impl_->GetSequenceManagerWeakPtr() : nullptr),
20       graceful_queue_shutdown_helper_(
21           impl_ ? impl_->GetGracefulQueueShutdownHelper() : nullptr) {}
22 
~TaskQueue()23 TaskQueue::~TaskQueue() {
24   // scoped_refptr guarantees us that this object isn't used.
25   if (!impl_)
26     return;
27   if (impl_->IsUnregistered())
28     return;
29   graceful_queue_shutdown_helper_->GracefullyShutdownTaskQueue(
30       TakeTaskQueueImpl());
31 }
32 
Task(TaskQueue::PostedTask task,TimeTicks desired_run_time)33 TaskQueue::Task::Task(TaskQueue::PostedTask task, TimeTicks desired_run_time)
34     : PendingTask(task.posted_from,
35                   std::move(task.callback),
36                   desired_run_time,
37                   task.nestable),
38       task_type_(task.task_type) {}
39 
TaskTiming(bool has_wall_time,bool has_thread_time)40 TaskQueue::TaskTiming::TaskTiming(bool has_wall_time, bool has_thread_time)
41     : has_wall_time_(has_wall_time), has_thread_time_(has_thread_time) {}
42 
RecordTaskStart(LazyNow * now)43 void TaskQueue::TaskTiming::RecordTaskStart(LazyNow* now) {
44   if (has_wall_time())
45     start_time_ = now->Now();
46   if (has_thread_time())
47     start_thread_time_ = base::ThreadTicks::Now();
48 }
49 
RecordTaskEnd(LazyNow * now)50 void TaskQueue::TaskTiming::RecordTaskEnd(LazyNow* now) {
51   if (has_wall_time())
52     end_time_ = now->Now();
53   if (has_thread_time())
54     end_thread_time_ = base::ThreadTicks::Now();
55 }
56 
PostedTask(OnceClosure callback,Location posted_from,TimeDelta delay,Nestable nestable,int task_type)57 TaskQueue::PostedTask::PostedTask(OnceClosure callback,
58                                   Location posted_from,
59                                   TimeDelta delay,
60                                   Nestable nestable,
61                                   int task_type)
62     : callback(std::move(callback)),
63       posted_from(posted_from),
64       delay(delay),
65       nestable(nestable),
66       task_type(task_type) {}
67 
PostedTask(PostedTask && move_from)68 TaskQueue::PostedTask::PostedTask(PostedTask&& move_from)
69     : callback(std::move(move_from.callback)),
70       posted_from(move_from.posted_from),
71       delay(move_from.delay),
72       nestable(move_from.nestable),
73       task_type(move_from.task_type) {}
74 
75 TaskQueue::PostedTask::~PostedTask() = default;
76 
ShutdownTaskQueue()77 void TaskQueue::ShutdownTaskQueue() {
78   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
79   AutoLock lock(impl_lock_);
80   if (!impl_)
81     return;
82   if (!sequence_manager_) {
83     impl_.reset();
84     return;
85   }
86   impl_->SetBlameContext(nullptr);
87   impl_->SetOnTaskStartedHandler(
88       internal::TaskQueueImpl::OnTaskStartedHandler());
89   impl_->SetOnTaskCompletedHandler(
90       internal::TaskQueueImpl::OnTaskCompletedHandler());
91   sequence_manager_->UnregisterTaskQueueImpl(TakeTaskQueueImpl());
92 }
93 
RunsTasksInCurrentSequence() const94 bool TaskQueue::RunsTasksInCurrentSequence() const {
95   return IsOnMainThread();
96 }
97 
PostDelayedTask(const Location & from_here,OnceClosure task,TimeDelta delay)98 bool TaskQueue::PostDelayedTask(const Location& from_here,
99                                 OnceClosure task,
100                                 TimeDelta delay) {
101   return PostTaskWithMetadata(
102       PostedTask(std::move(task), from_here, delay, Nestable::kNestable));
103 }
104 
PostNonNestableDelayedTask(const Location & from_here,OnceClosure task,TimeDelta delay)105 bool TaskQueue::PostNonNestableDelayedTask(const Location& from_here,
106                                            OnceClosure task,
107                                            TimeDelta delay) {
108   return PostTaskWithMetadata(
109       PostedTask(std::move(task), from_here, delay, Nestable::kNonNestable));
110 }
111 
PostTaskWithMetadata(PostedTask task)112 bool TaskQueue::PostTaskWithMetadata(PostedTask task) {
113   Optional<MoveableAutoLock> lock = AcquireImplReadLockIfNeeded();
114   if (!impl_)
115     return false;
116   internal::TaskQueueImpl::PostTaskResult result(
117       impl_->PostDelayedTask(std::move(task)));
118   if (result.success)
119     return true;
120   // If posting task was unsuccessful then |result| will contain
121   // the original task which should be destructed outside of the lock.
122   lock = nullopt;
123   // Task gets implicitly destructed here.
124   return false;
125 }
126 
127 std::unique_ptr<TaskQueue::QueueEnabledVoter>
CreateQueueEnabledVoter()128 TaskQueue::CreateQueueEnabledVoter() {
129   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
130   if (!impl_)
131     return nullptr;
132   return impl_->CreateQueueEnabledVoter(this);
133 }
134 
IsQueueEnabled() const135 bool TaskQueue::IsQueueEnabled() const {
136   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
137   if (!impl_)
138     return false;
139   return impl_->IsQueueEnabled();
140 }
141 
IsEmpty() const142 bool TaskQueue::IsEmpty() const {
143   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
144   if (!impl_)
145     return true;
146   return impl_->IsEmpty();
147 }
148 
GetNumberOfPendingTasks() const149 size_t TaskQueue::GetNumberOfPendingTasks() const {
150   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
151   if (!impl_)
152     return 0;
153   return impl_->GetNumberOfPendingTasks();
154 }
155 
HasTaskToRunImmediately() const156 bool TaskQueue::HasTaskToRunImmediately() const {
157   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
158   if (!impl_)
159     return false;
160   return impl_->HasTaskToRunImmediately();
161 }
162 
GetNextScheduledWakeUp()163 Optional<TimeTicks> TaskQueue::GetNextScheduledWakeUp() {
164   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
165   if (!impl_)
166     return nullopt;
167   return impl_->GetNextScheduledWakeUp();
168 }
169 
SetQueuePriority(TaskQueue::QueuePriority priority)170 void TaskQueue::SetQueuePriority(TaskQueue::QueuePriority priority) {
171   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
172   if (!impl_)
173     return;
174   impl_->SetQueuePriority(priority);
175 }
176 
GetQueuePriority() const177 TaskQueue::QueuePriority TaskQueue::GetQueuePriority() const {
178   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
179   if (!impl_)
180     return TaskQueue::QueuePriority::kLowPriority;
181   return impl_->GetQueuePriority();
182 }
183 
AddTaskObserver(MessageLoop::TaskObserver * task_observer)184 void TaskQueue::AddTaskObserver(MessageLoop::TaskObserver* task_observer) {
185   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
186   if (!impl_)
187     return;
188   impl_->AddTaskObserver(task_observer);
189 }
190 
RemoveTaskObserver(MessageLoop::TaskObserver * task_observer)191 void TaskQueue::RemoveTaskObserver(MessageLoop::TaskObserver* task_observer) {
192   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
193   if (!impl_)
194     return;
195   impl_->RemoveTaskObserver(task_observer);
196 }
197 
SetTimeDomain(TimeDomain * time_domain)198 void TaskQueue::SetTimeDomain(TimeDomain* time_domain) {
199   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
200   if (!impl_)
201     return;
202   impl_->SetTimeDomain(time_domain);
203 }
204 
GetTimeDomain() const205 TimeDomain* TaskQueue::GetTimeDomain() const {
206   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
207   if (!impl_)
208     return nullptr;
209   return impl_->GetTimeDomain();
210 }
211 
SetBlameContext(trace_event::BlameContext * blame_context)212 void TaskQueue::SetBlameContext(trace_event::BlameContext* blame_context) {
213   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
214   if (!impl_)
215     return;
216   impl_->SetBlameContext(blame_context);
217 }
218 
InsertFence(InsertFencePosition position)219 void TaskQueue::InsertFence(InsertFencePosition position) {
220   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
221   if (!impl_)
222     return;
223   impl_->InsertFence(position);
224 }
225 
InsertFenceAt(TimeTicks time)226 void TaskQueue::InsertFenceAt(TimeTicks time) {
227   impl_->InsertFenceAt(time);
228 }
229 
RemoveFence()230 void TaskQueue::RemoveFence() {
231   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
232   if (!impl_)
233     return;
234   impl_->RemoveFence();
235 }
236 
HasActiveFence()237 bool TaskQueue::HasActiveFence() {
238   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
239   if (!impl_)
240     return false;
241   return impl_->HasActiveFence();
242 }
243 
BlockedByFence() const244 bool TaskQueue::BlockedByFence() const {
245   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
246   if (!impl_)
247     return false;
248   return impl_->BlockedByFence();
249 }
250 
GetName() const251 const char* TaskQueue::GetName() const {
252   auto lock = AcquireImplReadLockIfNeeded();
253   if (!impl_)
254     return "";
255   return impl_->GetName();
256 }
257 
SetObserver(Observer * observer)258 void TaskQueue::SetObserver(Observer* observer) {
259   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
260   if (!impl_)
261     return;
262   if (observer) {
263     // Observer is guaranteed to outlive TaskQueue and TaskQueueImpl lifecycle
264     // is controlled by |this|.
265     impl_->SetOnNextWakeUpChangedCallback(
266         BindRepeating(&TaskQueue::Observer::OnQueueNextWakeUpChanged,
267                       Unretained(observer), Unretained(this)));
268   } else {
269     impl_->SetOnNextWakeUpChangedCallback(RepeatingCallback<void(TimeTicks)>());
270   }
271 }
272 
IsOnMainThread() const273 bool TaskQueue::IsOnMainThread() const {
274   return thread_id_ == PlatformThread::CurrentId();
275 }
276 
AcquireImplReadLockIfNeeded() const277 Optional<MoveableAutoLock> TaskQueue::AcquireImplReadLockIfNeeded() const {
278   if (IsOnMainThread())
279     return nullopt;
280   return MoveableAutoLock(impl_lock_);
281 }
282 
TakeTaskQueueImpl()283 std::unique_ptr<internal::TaskQueueImpl> TaskQueue::TakeTaskQueueImpl() {
284   DCHECK(impl_);
285   return std::move(impl_);
286 }
287 
288 }  // namespace sequence_manager
289 }  // namespace base
290