Home | History | Annotate | Download | only in sequence_manager
      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 
     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 
     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 
     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 
     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 
     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 
     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 
     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 
     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 
     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 
     94 bool TaskQueue::RunsTasksInCurrentSequence() const {
     95   return IsOnMainThread();
     96 }
     97 
     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 
    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 
    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>
    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 
    135 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 
    142 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 
    149 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 
    156 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 
    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 
    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 
    177 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 
    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 
    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 
    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 
    205 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 
    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 
    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 
    226 void TaskQueue::InsertFenceAt(TimeTicks time) {
    227   impl_->InsertFenceAt(time);
    228 }
    229 
    230 void TaskQueue::RemoveFence() {
    231   DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
    232   if (!impl_)
    233     return;
    234   impl_->RemoveFence();
    235 }
    236 
    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 
    244 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 
    251 const char* TaskQueue::GetName() const {
    252   auto lock = AcquireImplReadLockIfNeeded();
    253   if (!impl_)
    254     return "";
    255   return impl_->GetName();
    256 }
    257 
    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 
    273 bool TaskQueue::IsOnMainThread() const {
    274   return thread_id_ == PlatformThread::CurrentId();
    275 }
    276 
    277 Optional<MoveableAutoLock> TaskQueue::AcquireImplReadLockIfNeeded() const {
    278   if (IsOnMainThread())
    279     return nullopt;
    280   return MoveableAutoLock(impl_lock_);
    281 }
    282 
    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