| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "base/task_scheduler/scheduler_worker_thread.h" | 5 #include "base/task_scheduler/scheduler_worker_thread.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 | 21 |
| 22 namespace { | 22 namespace { |
| 23 | 23 |
| 24 // SchedulerWorkerThread that owns the current thread, if any. | 24 // SchedulerWorkerThread that owns the current thread, if any. |
| 25 LazyInstance<ThreadLocalPointer<const SchedulerTaskExecutor>>::Leaky | 25 LazyInstance<ThreadLocalPointer<const SchedulerTaskExecutor>>::Leaky |
| 26 tls_current_worker_thread = LAZY_INSTANCE_INITIALIZER; | 26 tls_current_worker_thread = LAZY_INSTANCE_INITIALIZER; |
| 27 | 27 |
| 28 // A task runner that runs tasks on a single SchedulerWorkerThread. | 28 // A task runner that runs tasks on a single SchedulerWorkerThread. |
| 29 class SchedulerSingleThreadTaskRunner : public SingleThreadTaskRunner { | 29 class SchedulerSingleThreadTaskRunner : public SingleThreadTaskRunner { |
| 30 public: | 30 public: |
| 31 SchedulerSingleThreadTaskRunner(const TaskTraits& traits, | 31 SchedulerSingleThreadTaskRunner( |
| 32 SchedulerTaskExecutor* executor, | 32 const TaskTraits& traits, |
| 33 TaskTracker* task_tracker, | 33 SchedulerTaskExecutor* executor, |
| 34 DelayedTaskManager* delayed_task_manager) | 34 TaskTracker* task_tracker, |
| 35 DelayedTaskManager* delayed_task_manager, |
| 36 base::subtle::Atomic32* num_single_thread_task_runners) |
| 35 : traits_(traits), | 37 : traits_(traits), |
| 36 executor_(executor), | 38 executor_(executor), |
| 37 task_tracker_(task_tracker), | 39 task_tracker_(task_tracker), |
| 38 delayed_task_manager_(delayed_task_manager) {} | 40 delayed_task_manager_(delayed_task_manager), |
| 41 num_single_thread_task_runners_(num_single_thread_task_runners) { |
| 42 DCHECK(executor_); |
| 43 DCHECK(task_tracker_); |
| 44 DCHECK(delayed_task_manager_); |
| 45 DCHECK(num_single_thread_task_runners_); |
| 46 |
| 47 base::subtle::NoBarrier_AtomicIncrement(num_single_thread_task_runners_, 1); |
| 48 } |
| 39 | 49 |
| 40 // SingleThreadTaskRunner: | 50 // SingleThreadTaskRunner: |
| 41 bool PostDelayedTask(const tracked_objects::Location& from_here, | 51 bool PostDelayedTask(const tracked_objects::Location& from_here, |
| 42 const Closure& closure, | 52 const Closure& closure, |
| 43 TimeDelta delay) override { | 53 TimeDelta delay) override { |
| 44 // Post the task as part of |sequence|. | 54 // Post the task as part of |sequence|. |
| 45 return PostTaskToExecutor(from_here, closure, traits_, delay, sequence_, | 55 return PostTaskToExecutor(from_here, closure, traits_, delay, sequence_, |
| 46 executor_, task_tracker_, delayed_task_manager_); | 56 executor_, task_tracker_, delayed_task_manager_); |
| 47 } | 57 } |
| 48 | 58 |
| 49 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, | 59 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
| 50 const Closure& closure, | 60 const Closure& closure, |
| 51 base::TimeDelta delay) override { | 61 base::TimeDelta delay) override { |
| 52 // Tasks are never nested within the task scheduler. | 62 // Tasks are never nested within the task scheduler. |
| 53 return PostDelayedTask(from_here, closure, delay); | 63 return PostDelayedTask(from_here, closure, delay); |
| 54 } | 64 } |
| 55 | 65 |
| 56 bool RunsTasksOnCurrentThread() const override { | 66 bool RunsTasksOnCurrentThread() const override { |
| 57 return tls_current_worker_thread.Get().Get() == executor_; | 67 return tls_current_worker_thread.Get().Get() == executor_; |
| 58 } | 68 } |
| 59 | 69 |
| 60 private: | 70 private: |
| 61 ~SchedulerSingleThreadTaskRunner() override = default; | 71 ~SchedulerSingleThreadTaskRunner() override { |
| 72 base::subtle::NoBarrier_AtomicIncrement(num_single_thread_task_runners_, |
| 73 -1); |
| 74 } |
| 62 | 75 |
| 63 // Sequence for all Tasks posted through this TaskRunner. | 76 // Sequence for all Tasks posted through this TaskRunner. |
| 64 const scoped_refptr<Sequence> sequence_ = new Sequence; | 77 const scoped_refptr<Sequence> sequence_ = new Sequence; |
| 65 | 78 |
| 66 const TaskTraits traits_; | 79 const TaskTraits traits_; |
| 67 SchedulerTaskExecutor* const executor_; | 80 SchedulerTaskExecutor* const executor_; |
| 68 TaskTracker* const task_tracker_; | 81 TaskTracker* const task_tracker_; |
| 69 DelayedTaskManager* const delayed_task_manager_; | 82 DelayedTaskManager* const delayed_task_manager_; |
| 70 | 83 |
| 84 // Number of single-thread TaskRunners associated with |executor_|. |
| 85 // Incremented by the constructor and decremented by the destructor. |
| 86 base::subtle::Atomic32* const num_single_thread_task_runners_; |
| 87 |
| 71 DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunner); | 88 DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunner); |
| 72 }; | 89 }; |
| 73 | 90 |
| 74 } // namespace | 91 } // namespace |
| 75 | 92 |
| 76 std::unique_ptr<SchedulerWorkerThread> | 93 std::unique_ptr<SchedulerWorkerThread> |
| 77 SchedulerWorkerThread::CreateSchedulerWorkerThread( | 94 SchedulerWorkerThread::CreateSchedulerWorkerThread( |
| 78 ThreadPriority thread_priority, | 95 ThreadPriority thread_priority, |
| 79 Delegate* delegate, | 96 Delegate* delegate, |
| 80 TaskTracker* task_tracker, | 97 TaskTracker* task_tracker, |
| 81 DelayedTaskManager* delayed_task_manager, | 98 DelayedTaskManager* delayed_task_manager, |
| 82 const PriorityQueue* predecessor_priority_queue) { | 99 const PriorityQueue* predecessor_priority_queue) { |
| 83 std::unique_ptr<SchedulerWorkerThread> worker_thread( | 100 std::unique_ptr<SchedulerWorkerThread> worker_thread( |
| 84 new SchedulerWorkerThread(thread_priority, delegate, task_tracker, | 101 new SchedulerWorkerThread(thread_priority, delegate, task_tracker, |
| 85 delayed_task_manager, | 102 delayed_task_manager, |
| 86 predecessor_priority_queue)); | 103 predecessor_priority_queue)); |
| 87 | 104 |
| 88 if (worker_thread->thread_handle_.is_null()) | 105 if (worker_thread->thread_handle_.is_null()) |
| 89 return nullptr; | 106 return nullptr; |
| 90 return worker_thread; | 107 return worker_thread; |
| 91 } | 108 } |
| 92 | 109 |
| 93 SchedulerWorkerThread::~SchedulerWorkerThread() { | 110 SchedulerWorkerThread::~SchedulerWorkerThread() { |
| 94 DCHECK(ShouldExitForTesting()); | 111 DCHECK(ShouldExitForTesting()); |
| 95 } | 112 } |
| 96 | 113 |
| 97 scoped_refptr<SingleThreadTaskRunner> | 114 scoped_refptr<SingleThreadTaskRunner> |
| 98 SchedulerWorkerThread::CreateTaskRunnerWithTraits(const TaskTraits& traits) { | 115 SchedulerWorkerThread::CreateTaskRunnerWithTraits(const TaskTraits& traits) { |
| 99 return make_scoped_refptr(new SchedulerSingleThreadTaskRunner( | 116 return make_scoped_refptr(new SchedulerSingleThreadTaskRunner( |
| 100 traits, this, task_tracker_, delayed_task_manager_)); | 117 traits, this, task_tracker_, delayed_task_manager_, |
| 118 &num_single_thread_task_runners_)); |
| 119 } |
| 120 |
| 121 size_t SchedulerWorkerThread::GetNumSingleThreadTaskRunners() const { |
| 122 return base::subtle::NoBarrier_Load(&num_single_thread_task_runners_); |
| 101 } | 123 } |
| 102 | 124 |
| 103 void SchedulerWorkerThread::WakeUp() { | 125 void SchedulerWorkerThread::WakeUp() { |
| 104 wake_up_event_.Signal(); | 126 wake_up_event_.Signal(); |
| 105 } | 127 } |
| 106 | 128 |
| 107 void SchedulerWorkerThread::JoinForTesting() { | 129 void SchedulerWorkerThread::JoinForTesting() { |
| 108 { | 130 { |
| 109 AutoSchedulerLock auto_lock(should_exit_for_testing_lock_); | 131 AutoSchedulerLock auto_lock(should_exit_for_testing_lock_); |
| 110 should_exit_for_testing_ = true; | 132 should_exit_for_testing_ = true; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 137 : wake_up_event_(false, false), | 159 : wake_up_event_(false, false), |
| 138 single_threaded_priority_queue_(predecessor_priority_queue), | 160 single_threaded_priority_queue_(predecessor_priority_queue), |
| 139 delegate_(delegate), | 161 delegate_(delegate), |
| 140 task_tracker_(task_tracker), | 162 task_tracker_(task_tracker), |
| 141 delayed_task_manager_(delayed_task_manager) { | 163 delayed_task_manager_(delayed_task_manager) { |
| 142 DCHECK(delegate_); | 164 DCHECK(delegate_); |
| 143 DCHECK(task_tracker_); | 165 DCHECK(task_tracker_); |
| 144 DCHECK(delayed_task_manager_); | 166 DCHECK(delayed_task_manager_); |
| 145 DCHECK(predecessor_priority_queue); | 167 DCHECK(predecessor_priority_queue); |
| 146 | 168 |
| 169 base::subtle::NoBarrier_Store(&num_single_thread_task_runners_, 0); |
| 170 |
| 147 const size_t kDefaultStackSize = 0; | 171 const size_t kDefaultStackSize = 0; |
| 148 PlatformThread::CreateWithPriority(kDefaultStackSize, this, &thread_handle_, | 172 PlatformThread::CreateWithPriority(kDefaultStackSize, this, &thread_handle_, |
| 149 thread_priority); | 173 thread_priority); |
| 150 } | 174 } |
| 151 | 175 |
| 152 void SchedulerWorkerThread::ThreadMain() { | 176 void SchedulerWorkerThread::ThreadMain() { |
| 153 delegate_->OnMainEntry(); | 177 delegate_->OnMainEntry(); |
| 154 tls_current_worker_thread.Get().Set(this); | 178 tls_current_worker_thread.Get().Set(this); |
| 155 | 179 |
| 156 // A SchedulerWorkerThread starts out sleeping. | 180 // A SchedulerWorkerThread starts out sleeping. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 } | 220 } |
| 197 } | 221 } |
| 198 | 222 |
| 199 bool SchedulerWorkerThread::ShouldExitForTesting() const { | 223 bool SchedulerWorkerThread::ShouldExitForTesting() const { |
| 200 AutoSchedulerLock auto_lock(should_exit_for_testing_lock_); | 224 AutoSchedulerLock auto_lock(should_exit_for_testing_lock_); |
| 201 return should_exit_for_testing_; | 225 return should_exit_for_testing_; |
| 202 } | 226 } |
| 203 | 227 |
| 204 } // namespace internal | 228 } // namespace internal |
| 205 } // namespace base | 229 } // namespace base |
| OLD | NEW |