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 |