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 : priority_hint_(priority_hint), |
210 scoped_refptr<SchedulerWorker> worker( | 210 delegate_(std::move(delegate)), |
211 new SchedulerWorker(priority_hint, std::move(delegate), task_tracker, | 211 task_tracker_(task_tracker) |
212 backward_compatibility)); | 212 #if defined(OS_WIN) |
213 // Creation happens before any other thread can reference this one, so no | 213 , |
214 // synchronization is necessary. | 214 backward_compatibility_(backward_compatibility) |
215 if (initial_state == SchedulerWorker::InitialState::ALIVE) { | 215 #endif |
216 worker->CreateThread(); | 216 { |
217 if (!worker->thread_) { | 217 DCHECK(delegate_); |
218 return nullptr; | 218 DCHECK(task_tracker_); |
219 } | 219 } |
220 | |
221 bool SchedulerWorker::Start(InitialState initial_state) { | |
222 AutoSchedulerLock auto_lock(thread_lock_); | |
223 DCHECK(!started_); | |
224 DCHECK(!thread_); | |
225 | |
226 if (should_exit_.IsSet() || join_called_for_testing_.IsSet()) | |
227 return true; | |
228 | |
229 started_ = true; | |
230 | |
231 if (initial_state == InitialState::ALIVE) { | |
232 CreateThreadAssertSynchronized(); | |
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 CreateThreadAssertSynchronized(); |
232 | 246 |
(...skipping 26 matching lines...) Expand all Loading... | |
259 AutoSchedulerLock auto_lock(thread_lock_); | 273 AutoSchedulerLock auto_lock(thread_lock_); |
260 return !!thread_; | 274 return !!thread_; |
261 } | 275 } |
262 | 276 |
263 void SchedulerWorker::Cleanup() { | 277 void SchedulerWorker::Cleanup() { |
264 // |should_exit_| is synchronized with |thread_| for writes here so that we | 278 // |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 | 279 // can maintain access to |thread_| for wakeup. Otherwise, the thread may take |
266 // away |thread_| for destruction. | 280 // away |thread_| for destruction. |
267 AutoSchedulerLock auto_lock(thread_lock_); | 281 AutoSchedulerLock auto_lock(thread_lock_); |
268 DCHECK(!should_exit_.IsSet()); | 282 DCHECK(!should_exit_.IsSet()); |
269 if (thread_) { | 283 should_exit_.Set(); |
270 should_exit_.Set(); | 284 if (thread_) |
271 thread_->WakeUp(); | 285 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 } | 286 } |
291 | 287 |
292 SchedulerWorker::~SchedulerWorker() { | 288 SchedulerWorker::~SchedulerWorker() { |
293 // It is unexpected for |thread_| to be alive and for SchedulerWorker to | 289 // It is unexpected for |thread_| to be alive and for SchedulerWorker to |
294 // destroy since SchedulerWorker owns the delegate needed by |thread_|. | 290 // destroy since SchedulerWorker owns the delegate needed by |thread_|. |
295 // For testing, this generally means JoinForTesting was not called. | 291 // For testing, this generally means JoinForTesting was not called. |
296 DCHECK(!thread_); | 292 DCHECK(!thread_); |
297 } | 293 } |
298 | 294 |
299 std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::DetachThreadObject( | 295 std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::DetachThreadObject( |
(...skipping 14 matching lines...) Expand all Loading... | |
314 | 310 |
315 if (detach_notify == DetachNotify::DELEGATE) { | 311 if (detach_notify == DetachNotify::DELEGATE) { |
316 // Call OnDetach() within the scope of |thread_lock_| to prevent the | 312 // Call OnDetach() within the scope of |thread_lock_| to prevent the |
317 // delegate from being used concurrently from an old and a new thread. | 313 // delegate from being used concurrently from an old and a new thread. |
318 delegate_->OnDetach(); | 314 delegate_->OnDetach(); |
319 } | 315 } |
320 | 316 |
321 return std::move(thread_); | 317 return std::move(thread_); |
322 } | 318 } |
323 | 319 |
324 void SchedulerWorker::CreateThread() { | 320 void SchedulerWorker::CreateThread() { |
gab
2017/04/10 18:04:56
Last caller of this is now CreateThreadAssertSynch
fdoray
2017/04/10 19:05:00
Done.
| |
325 thread_ = Thread::Create(make_scoped_refptr(this)); | 321 if (started_) |
322 thread_ = Thread::Create(make_scoped_refptr(this)); | |
326 } | 323 } |
327 | 324 |
328 void SchedulerWorker::CreateThreadAssertSynchronized() { | 325 void SchedulerWorker::CreateThreadAssertSynchronized() { |
329 thread_lock_.AssertAcquired(); | 326 thread_lock_.AssertAcquired(); |
330 CreateThread(); | 327 CreateThread(); |
331 } | 328 } |
332 | 329 |
333 bool SchedulerWorker::ShouldExit() { | 330 bool SchedulerWorker::ShouldExit() { |
334 // The ordering of the checks is important below. This SchedulerWorker may be | 331 // The ordering of the checks is important below. This SchedulerWorker may be |
335 // released and outlive |task_tracker_| in unit tests. However, when the | 332 // released and outlive |task_tracker_| in unit tests. However, when the |
336 // SchedulerWorker is released, |should_exit_| will be set, so check that | 333 // SchedulerWorker is released, |should_exit_| will be set, so check that |
337 // first. | 334 // first. |
338 return should_exit_.IsSet() || join_called_for_testing_.IsSet() || | 335 return should_exit_.IsSet() || join_called_for_testing_.IsSet() || |
339 task_tracker_->IsShutdownComplete(); | 336 task_tracker_->IsShutdownComplete(); |
340 } | 337 } |
341 | 338 |
342 } // namespace internal | 339 } // namespace internal |
343 } // namespace base | 340 } // namespace base |
OLD | NEW |