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 13 matching lines...) Expand all Loading... |
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 // Constructs a SchedulerSingleThreadTaskRunner which can be used to post | 31 // Constructs a SchedulerSingleThreadTaskRunner which can be used to post |
32 // tasks so long as |executor| is alive. | 32 // tasks so long as |executor| is alive. |
33 // TODO(robliao): Find a concrete way to manage |executor|'s memory. | 33 // TODO(robliao): Find a concrete way to manage |executor|'s memory. |
34 SchedulerSingleThreadTaskRunner(const TaskTraits& traits, | 34 SchedulerSingleThreadTaskRunner( |
35 SchedulerTaskExecutor* executor, | 35 const TaskTraits& traits, |
36 TaskTracker* task_tracker, | 36 SchedulerTaskExecutor* executor, |
37 DelayedTaskManager* delayed_task_manager) | 37 TaskTracker* task_tracker, |
| 38 DelayedTaskManager* delayed_task_manager, |
| 39 base::subtle::Atomic32* num_single_thread_task_runners) |
38 : traits_(traits), | 40 : traits_(traits), |
39 executor_(executor), | 41 executor_(executor), |
40 task_tracker_(task_tracker), | 42 task_tracker_(task_tracker), |
41 delayed_task_manager_(delayed_task_manager) {} | 43 delayed_task_manager_(delayed_task_manager), |
| 44 num_single_thread_task_runners_(num_single_thread_task_runners) { |
| 45 DCHECK(executor_); |
| 46 DCHECK(task_tracker_); |
| 47 DCHECK(delayed_task_manager_); |
| 48 DCHECK(num_single_thread_task_runners_); |
| 49 |
| 50 base::subtle::NoBarrier_AtomicIncrement(num_single_thread_task_runners_, 1); |
| 51 } |
42 | 52 |
43 // SingleThreadTaskRunner: | 53 // SingleThreadTaskRunner: |
44 bool PostDelayedTask(const tracked_objects::Location& from_here, | 54 bool PostDelayedTask(const tracked_objects::Location& from_here, |
45 const Closure& closure, | 55 const Closure& closure, |
46 TimeDelta delay) override { | 56 TimeDelta delay) override { |
47 // Post the task as part of |sequence_|. | 57 // Post the task as part of |sequence_|. |
48 return PostTaskToExecutor( | 58 return PostTaskToExecutor( |
49 WrapUnique( | 59 WrapUnique( |
50 new Task(from_here, closure, traits_, | 60 new Task(from_here, closure, traits_, |
51 delay.is_zero() ? TimeTicks() : TimeTicks::Now() + delay)), | 61 delay.is_zero() ? TimeTicks() : TimeTicks::Now() + delay)), |
52 sequence_, executor_, task_tracker_, delayed_task_manager_); | 62 sequence_, executor_, task_tracker_, delayed_task_manager_); |
53 } | 63 } |
54 | 64 |
55 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, | 65 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
56 const Closure& closure, | 66 const Closure& closure, |
57 base::TimeDelta delay) override { | 67 base::TimeDelta delay) override { |
58 // Tasks are never nested within the task scheduler. | 68 // Tasks are never nested within the task scheduler. |
59 return PostDelayedTask(from_here, closure, delay); | 69 return PostDelayedTask(from_here, closure, delay); |
60 } | 70 } |
61 | 71 |
62 bool RunsTasksOnCurrentThread() const override { | 72 bool RunsTasksOnCurrentThread() const override { |
63 return tls_current_worker_thread.Get().Get() == executor_; | 73 return tls_current_worker_thread.Get().Get() == executor_; |
64 } | 74 } |
65 | 75 |
66 private: | 76 private: |
67 ~SchedulerSingleThreadTaskRunner() override = default; | 77 ~SchedulerSingleThreadTaskRunner() override { |
| 78 base::subtle::NoBarrier_AtomicIncrement(num_single_thread_task_runners_, |
| 79 -1); |
| 80 } |
68 | 81 |
69 // Sequence for all Tasks posted through this TaskRunner. | 82 // Sequence for all Tasks posted through this TaskRunner. |
70 const scoped_refptr<Sequence> sequence_ = new Sequence; | 83 const scoped_refptr<Sequence> sequence_ = new Sequence; |
71 | 84 |
72 const TaskTraits traits_; | 85 const TaskTraits traits_; |
73 SchedulerTaskExecutor* const executor_; | 86 SchedulerTaskExecutor* const executor_; |
74 TaskTracker* const task_tracker_; | 87 TaskTracker* const task_tracker_; |
75 DelayedTaskManager* const delayed_task_manager_; | 88 DelayedTaskManager* const delayed_task_manager_; |
76 | 89 |
| 90 // Number of single-thread TaskRunners associated with |executor_|. |
| 91 // Incremented by the constructor and decremented by the destructor. |
| 92 base::subtle::Atomic32* const num_single_thread_task_runners_; |
| 93 |
77 DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunner); | 94 DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunner); |
78 }; | 95 }; |
79 | 96 |
80 } // namespace | 97 } // namespace |
81 | 98 |
82 std::unique_ptr<SchedulerWorkerThread> | 99 std::unique_ptr<SchedulerWorkerThread> |
83 SchedulerWorkerThread::CreateSchedulerWorkerThread( | 100 SchedulerWorkerThread::CreateSchedulerWorkerThread( |
84 ThreadPriority thread_priority, | 101 ThreadPriority thread_priority, |
85 Delegate* delegate, | 102 Delegate* delegate, |
86 TaskTracker* task_tracker, | 103 TaskTracker* task_tracker, |
87 DelayedTaskManager* delayed_task_manager, | 104 DelayedTaskManager* delayed_task_manager, |
88 const PriorityQueue* predecessor_priority_queue) { | 105 const PriorityQueue* predecessor_priority_queue) { |
89 std::unique_ptr<SchedulerWorkerThread> worker_thread( | 106 std::unique_ptr<SchedulerWorkerThread> worker_thread( |
90 new SchedulerWorkerThread(thread_priority, delegate, task_tracker, | 107 new SchedulerWorkerThread(thread_priority, delegate, task_tracker, |
91 delayed_task_manager, | 108 delayed_task_manager, |
92 predecessor_priority_queue)); | 109 predecessor_priority_queue)); |
93 | 110 |
94 if (worker_thread->thread_handle_.is_null()) | 111 if (worker_thread->thread_handle_.is_null()) |
95 return nullptr; | 112 return nullptr; |
96 return worker_thread; | 113 return worker_thread; |
97 } | 114 } |
98 | 115 |
99 SchedulerWorkerThread::~SchedulerWorkerThread() { | 116 SchedulerWorkerThread::~SchedulerWorkerThread() { |
100 DCHECK(ShouldExitForTesting()); | 117 DCHECK(ShouldExitForTesting()); |
101 } | 118 } |
102 | 119 |
103 scoped_refptr<SingleThreadTaskRunner> | 120 scoped_refptr<SingleThreadTaskRunner> |
104 SchedulerWorkerThread::CreateTaskRunnerWithTraits(const TaskTraits& traits) { | 121 SchedulerWorkerThread::CreateTaskRunnerWithTraits(const TaskTraits& traits) { |
105 return make_scoped_refptr(new SchedulerSingleThreadTaskRunner( | 122 return make_scoped_refptr(new SchedulerSingleThreadTaskRunner( |
106 traits, this, task_tracker_, delayed_task_manager_)); | 123 traits, this, task_tracker_, delayed_task_manager_, |
| 124 &num_single_thread_task_runners_)); |
| 125 } |
| 126 |
| 127 size_t SchedulerWorkerThread::GetNumSingleThreadTaskRunners() const { |
| 128 return base::subtle::NoBarrier_Load(&num_single_thread_task_runners_); |
107 } | 129 } |
108 | 130 |
109 void SchedulerWorkerThread::WakeUp() { | 131 void SchedulerWorkerThread::WakeUp() { |
110 wake_up_event_.Signal(); | 132 wake_up_event_.Signal(); |
111 } | 133 } |
112 | 134 |
113 void SchedulerWorkerThread::JoinForTesting() { | 135 void SchedulerWorkerThread::JoinForTesting() { |
114 { | 136 { |
115 AutoSchedulerLock auto_lock(should_exit_for_testing_lock_); | 137 AutoSchedulerLock auto_lock(should_exit_for_testing_lock_); |
116 should_exit_for_testing_ = true; | 138 should_exit_for_testing_ = true; |
(...skipping 28 matching lines...) Expand all Loading... |
145 : wake_up_event_(false, false), | 167 : wake_up_event_(false, false), |
146 single_threaded_priority_queue_(predecessor_priority_queue), | 168 single_threaded_priority_queue_(predecessor_priority_queue), |
147 delegate_(delegate), | 169 delegate_(delegate), |
148 task_tracker_(task_tracker), | 170 task_tracker_(task_tracker), |
149 delayed_task_manager_(delayed_task_manager) { | 171 delayed_task_manager_(delayed_task_manager) { |
150 DCHECK(delegate_); | 172 DCHECK(delegate_); |
151 DCHECK(task_tracker_); | 173 DCHECK(task_tracker_); |
152 DCHECK(delayed_task_manager_); | 174 DCHECK(delayed_task_manager_); |
153 DCHECK(predecessor_priority_queue); | 175 DCHECK(predecessor_priority_queue); |
154 | 176 |
| 177 base::subtle::NoBarrier_Store(&num_single_thread_task_runners_, 0); |
| 178 |
155 const size_t kDefaultStackSize = 0; | 179 const size_t kDefaultStackSize = 0; |
156 PlatformThread::CreateWithPriority(kDefaultStackSize, this, &thread_handle_, | 180 PlatformThread::CreateWithPriority(kDefaultStackSize, this, &thread_handle_, |
157 thread_priority); | 181 thread_priority); |
158 } | 182 } |
159 | 183 |
160 void SchedulerWorkerThread::ThreadMain() { | 184 void SchedulerWorkerThread::ThreadMain() { |
161 delegate_->OnMainEntry(); | 185 delegate_->OnMainEntry(); |
162 tls_current_worker_thread.Get().Set(this); | 186 tls_current_worker_thread.Get().Set(this); |
163 | 187 |
164 // A SchedulerWorkerThread starts out sleeping. | 188 // A SchedulerWorkerThread starts out sleeping. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 } | 228 } |
205 } | 229 } |
206 | 230 |
207 bool SchedulerWorkerThread::ShouldExitForTesting() const { | 231 bool SchedulerWorkerThread::ShouldExitForTesting() const { |
208 AutoSchedulerLock auto_lock(should_exit_for_testing_lock_); | 232 AutoSchedulerLock auto_lock(should_exit_for_testing_lock_); |
209 return should_exit_for_testing_; | 233 return should_exit_for_testing_; |
210 } | 234 } |
211 | 235 |
212 } // namespace internal | 236 } // namespace internal |
213 } // namespace base | 237 } // namespace base |
OLD | NEW |