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.h" | 5 #include "base/task_scheduler/scheduler_worker.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 if (sleep_time.is_max()) { | 194 if (sleep_time.is_max()) { |
195 // Calling TimedWait with TimeDelta::Max is not recommended per | 195 // Calling TimedWait with TimeDelta::Max is not recommended per |
196 // http://crbug.com/465948. | 196 // http://crbug.com/465948. |
197 wake_up_event->Wait(); | 197 wake_up_event->Wait(); |
198 } else { | 198 } else { |
199 wake_up_event->TimedWait(sleep_time); | 199 wake_up_event->TimedWait(sleep_time); |
200 } | 200 } |
201 wake_up_event->Reset(); | 201 wake_up_event->Reset(); |
202 } | 202 } |
203 | 203 |
204 scoped_refptr<SchedulerWorker> SchedulerWorker::Create( | 204 SchedulerWorker::SchedulerWorker( |
205 ThreadPriority priority_hint, | 205 ThreadPriority priority_hint, |
206 std::unique_ptr<Delegate> delegate, | 206 std::unique_ptr<Delegate> delegate, |
207 TaskTracker* task_tracker, | 207 TaskTracker* task_tracker, |
208 InitialState initial_state, | 208 SchedulerBackwardCompatibility backward_compatibility, |
209 SchedulerBackwardCompatibility backward_compatibility) { | 209 InitialState initial_state) |
210 scoped_refptr<SchedulerWorker> worker( | 210 : priority_hint_(priority_hint), |
211 new SchedulerWorker(priority_hint, std::move(delegate), task_tracker, | 211 delegate_(std::move(delegate)), |
212 backward_compatibility)); | 212 task_tracker_(task_tracker), |
213 // Creation happens before any other thread can reference this one, so no | 213 #if defined(OS_WIN) |
214 // synchronization is necessary. | 214 backward_compatibility_(backward_compatibility), |
215 if (initial_state == SchedulerWorker::InitialState::ALIVE) { | 215 #endif |
216 worker->CreateThread(); | 216 initial_state_(initial_state) { |
217 if (!worker->thread_) { | 217 DCHECK(delegate_); |
218 return nullptr; | 218 DCHECK(task_tracker_); |
219 } | 219 } |
| 220 |
| 221 bool SchedulerWorker::Start() { |
| 222 AutoSchedulerLock auto_lock(thread_lock_); |
| 223 DCHECK(!started_); |
| 224 DCHECK(!thread_); |
| 225 |
| 226 if (should_exit_.IsSet()) |
| 227 return true; |
| 228 |
| 229 started_ = true; |
| 230 |
| 231 if (initial_state_ == InitialState::ALIVE) { |
| 232 CreateThread(); |
| 233 return !!thread_; |
220 } | 234 } |
221 | 235 |
222 return worker; | 236 return true; |
223 } | 237 } |
224 | 238 |
225 void SchedulerWorker::WakeUp() { | 239 void SchedulerWorker::WakeUp() { |
226 AutoSchedulerLock auto_lock(thread_lock_); | 240 AutoSchedulerLock auto_lock(thread_lock_); |
227 | 241 |
228 DCHECK(!join_called_for_testing_.IsSet()); | 242 DCHECK(!join_called_for_testing_.IsSet()); |
229 | 243 |
230 if (!thread_) | 244 if (!thread_) |
231 CreateThreadAssertSynchronized(); | 245 CreateThread(); |
232 | 246 |
233 if (thread_) | 247 if (thread_) |
234 thread_->WakeUp(); | 248 thread_->WakeUp(); |
235 } | 249 } |
236 | 250 |
237 void SchedulerWorker::JoinForTesting() { | 251 void SchedulerWorker::JoinForTesting() { |
| 252 DCHECK(started_); |
238 DCHECK(!join_called_for_testing_.IsSet()); | 253 DCHECK(!join_called_for_testing_.IsSet()); |
239 join_called_for_testing_.Set(); | 254 join_called_for_testing_.Set(); |
240 | 255 |
241 std::unique_ptr<Thread> thread; | 256 std::unique_ptr<Thread> thread; |
242 | 257 |
243 { | 258 { |
244 AutoSchedulerLock auto_lock(thread_lock_); | 259 AutoSchedulerLock auto_lock(thread_lock_); |
245 | 260 |
246 if (thread_) { | 261 if (thread_) { |
247 // Make sure the thread is awake. It will see that | 262 // Make sure the thread is awake. It will see that |
(...skipping 11 matching lines...) Expand all Loading... |
259 AutoSchedulerLock auto_lock(thread_lock_); | 274 AutoSchedulerLock auto_lock(thread_lock_); |
260 return !!thread_; | 275 return !!thread_; |
261 } | 276 } |
262 | 277 |
263 void SchedulerWorker::Cleanup() { | 278 void SchedulerWorker::Cleanup() { |
264 // |should_exit_| is synchronized with |thread_| for writes here so that we | 279 // |should_exit_| is synchronized with |thread_| for writes here so that we |
265 // can maintain access to |thread_| for wakeup. Otherwise, the thread may take | 280 // can maintain access to |thread_| for wakeup. Otherwise, the thread may take |
266 // away |thread_| for destruction. | 281 // away |thread_| for destruction. |
267 AutoSchedulerLock auto_lock(thread_lock_); | 282 AutoSchedulerLock auto_lock(thread_lock_); |
268 DCHECK(!should_exit_.IsSet()); | 283 DCHECK(!should_exit_.IsSet()); |
269 if (thread_) { | 284 should_exit_.Set(); |
270 should_exit_.Set(); | 285 if (thread_) |
271 thread_->WakeUp(); | 286 thread_->WakeUp(); |
272 } | |
273 } | |
274 | |
275 SchedulerWorker::SchedulerWorker( | |
276 ThreadPriority priority_hint, | |
277 std::unique_ptr<Delegate> delegate, | |
278 TaskTracker* task_tracker, | |
279 SchedulerBackwardCompatibility backward_compatibility) | |
280 : priority_hint_(priority_hint), | |
281 delegate_(std::move(delegate)), | |
282 task_tracker_(task_tracker) | |
283 #if defined(OS_WIN) | |
284 , | |
285 backward_compatibility_(backward_compatibility) | |
286 #endif | |
287 { | |
288 DCHECK(delegate_); | |
289 DCHECK(task_tracker_); | |
290 } | 287 } |
291 | 288 |
292 SchedulerWorker::~SchedulerWorker() { | 289 SchedulerWorker::~SchedulerWorker() { |
293 // It is unexpected for |thread_| to be alive and for SchedulerWorker to | 290 // It is unexpected for |thread_| to be alive and for SchedulerWorker to |
294 // destroy since SchedulerWorker owns the delegate needed by |thread_|. | 291 // destroy since SchedulerWorker owns the delegate needed by |thread_|. |
295 // For testing, this generally means JoinForTesting was not called. | 292 // For testing, this generally means JoinForTesting was not called. |
296 DCHECK(!thread_); | 293 DCHECK(!thread_); |
297 } | 294 } |
298 | 295 |
299 std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::DetachThreadObject( | 296 std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::DetachThreadObject( |
(...skipping 15 matching lines...) Expand all Loading... |
315 if (detach_notify == DetachNotify::DELEGATE) { | 312 if (detach_notify == DetachNotify::DELEGATE) { |
316 // Call OnDetach() within the scope of |thread_lock_| to prevent the | 313 // Call OnDetach() within the scope of |thread_lock_| to prevent the |
317 // delegate from being used concurrently from an old and a new thread. | 314 // delegate from being used concurrently from an old and a new thread. |
318 delegate_->OnDetach(); | 315 delegate_->OnDetach(); |
319 } | 316 } |
320 | 317 |
321 return std::move(thread_); | 318 return std::move(thread_); |
322 } | 319 } |
323 | 320 |
324 void SchedulerWorker::CreateThread() { | 321 void SchedulerWorker::CreateThread() { |
325 thread_ = Thread::Create(make_scoped_refptr(this)); | |
326 } | |
327 | |
328 void SchedulerWorker::CreateThreadAssertSynchronized() { | |
329 thread_lock_.AssertAcquired(); | 322 thread_lock_.AssertAcquired(); |
330 CreateThread(); | 323 if (started_) |
| 324 thread_ = Thread::Create(make_scoped_refptr(this)); |
331 } | 325 } |
332 | 326 |
333 bool SchedulerWorker::ShouldExit() { | 327 bool SchedulerWorker::ShouldExit() { |
334 // The ordering of the checks is important below. This SchedulerWorker may be | 328 // The ordering of the checks is important below. This SchedulerWorker may be |
335 // released and outlive |task_tracker_| in unit tests. However, when the | 329 // released and outlive |task_tracker_| in unit tests. However, when the |
336 // SchedulerWorker is released, |should_exit_| will be set, so check that | 330 // SchedulerWorker is released, |should_exit_| will be set, so check that |
337 // first. | 331 // first. |
338 return should_exit_.IsSet() || join_called_for_testing_.IsSet() || | 332 return should_exit_.IsSet() || join_called_for_testing_.IsSet() || |
339 task_tracker_->IsShutdownComplete(); | 333 task_tracker_->IsShutdownComplete(); |
340 } | 334 } |
341 | 335 |
342 } // namespace internal | 336 } // namespace internal |
343 } // namespace base | 337 } // namespace base |
OLD | NEW |