Chromium Code Reviews| 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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 | 209 |
| 210 SchedulerWorker::~SchedulerWorker() { | 210 SchedulerWorker::~SchedulerWorker() { |
| 211 // It is unexpected for |thread_| to be alive and for SchedulerWorker to | 211 // It is unexpected for |thread_| to be alive and for SchedulerWorker to |
| 212 // destroy since SchedulerWorker owns the delegate needed by |thread_|. | 212 // destroy since SchedulerWorker owns the delegate needed by |thread_|. |
| 213 // For testing, this generally means JoinForTesting was not called. | 213 // For testing, this generally means JoinForTesting was not called. |
| 214 DCHECK(!thread_); | 214 DCHECK(!thread_); |
| 215 } | 215 } |
| 216 | 216 |
| 217 void SchedulerWorker::WakeUp() { | 217 void SchedulerWorker::WakeUp() { |
| 218 AutoSchedulerLock auto_lock(thread_lock_); | 218 AutoSchedulerLock auto_lock(thread_lock_); |
| 219 | |
| 220 DCHECK(!should_exit_for_testing_.IsSet()); | |
| 221 | |
| 219 if (!thread_) | 222 if (!thread_) |
| 220 CreateThreadAssertSynchronized(); | 223 CreateThreadAssertSynchronized(); |
| 221 | 224 |
| 222 if (thread_) | 225 if (thread_) |
| 223 thread_->WakeUp(); | 226 thread_->WakeUp(); |
| 224 } | 227 } |
| 225 | 228 |
| 226 void SchedulerWorker::JoinForTesting() { | 229 void SchedulerWorker::JoinForTesting() { |
| 227 DCHECK(!should_exit_for_testing_.IsSet()); | 230 DCHECK(!should_exit_for_testing_.IsSet()); |
| 228 should_exit_for_testing_.Set(); | 231 should_exit_for_testing_.Set(); |
| 229 | 232 |
| 230 WakeUp(); | 233 std::unique_ptr<Thread> thread; |
| 231 | 234 |
| 232 // Normally holding a lock and joining is dangerous. However, since this is | 235 { |
| 233 // only for testing, we're okay since the only scenario that could impact this | 236 AutoSchedulerLock auto_lock(thread_lock_); |
| 234 // is a call to Detach, which is disallowed by having the delegate always | |
| 235 // return false for the CanDetach call. | |
| 236 AutoSchedulerLock auto_lock(thread_lock_); | |
| 237 if (thread_) | |
| 238 thread_->Join(); | |
| 239 | 237 |
| 240 thread_.reset(); | 238 if (thread_) { |
| 239 // Wake-up the thread. It will see that |should_exit_for_testing_| is set | |
|
gab
2017/01/17 21:24:25
s/Wake-up the thread/Make sure the thread is awake
fdoray
2017/01/17 23:51:00
Done.
| |
| 240 // and exit sortly after. | |
|
gab
2017/01/17 21:24:25
s/sortly/shortly/
fdoray
2017/01/17 23:51:00
Done.
| |
| 241 thread_->WakeUp(); | |
| 242 thread = std::move(thread_); | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 if (thread) | |
| 247 thread->Join(); | |
| 241 } | 248 } |
| 242 | 249 |
| 243 bool SchedulerWorker::ThreadAliveForTesting() const { | 250 bool SchedulerWorker::ThreadAliveForTesting() const { |
| 244 AutoSchedulerLock auto_lock(thread_lock_); | 251 AutoSchedulerLock auto_lock(thread_lock_); |
| 245 return !!thread_; | 252 return !!thread_; |
| 246 } | 253 } |
| 247 | 254 |
| 248 SchedulerWorker::SchedulerWorker(ThreadPriority priority_hint, | 255 SchedulerWorker::SchedulerWorker(ThreadPriority priority_hint, |
| 249 std::unique_ptr<Delegate> delegate, | 256 std::unique_ptr<Delegate> delegate, |
| 250 TaskTracker* task_tracker) | 257 TaskTracker* task_tracker) |
| 251 : priority_hint_(priority_hint), | 258 : priority_hint_(priority_hint), |
| 252 delegate_(std::move(delegate)), | 259 delegate_(std::move(delegate)), |
| 253 task_tracker_(task_tracker) { | 260 task_tracker_(task_tracker) { |
| 254 DCHECK(delegate_); | 261 DCHECK(delegate_); |
| 255 DCHECK(task_tracker_); | 262 DCHECK(task_tracker_); |
| 256 } | 263 } |
| 257 | 264 |
| 258 std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::Detach() { | 265 std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::Detach() { |
| 259 DCHECK(!should_exit_for_testing_.IsSet()) << "Worker was already joined"; | |
| 260 AutoSchedulerLock auto_lock(thread_lock_); | 266 AutoSchedulerLock auto_lock(thread_lock_); |
| 267 | |
| 268 // Do not detach if the thread is being joined. | |
| 269 if (!thread_) { | |
| 270 DCHECK(should_exit_for_testing_.IsSet()); | |
| 271 return nullptr; | |
| 272 } | |
| 273 | |
| 261 // If a wakeup is pending, then a WakeUp() came in while we were deciding to | 274 // If a wakeup is pending, then a WakeUp() came in while we were deciding to |
| 262 // detach. This means we can't go away anymore since we would break the | 275 // detach. This means we can't go away anymore since we would break the |
| 263 // guarantee that we call GetWork() after a successful wakeup. | 276 // guarantee that we call GetWork() after a successful wakeup. |
| 264 if (thread_->IsWakeUpPending()) | 277 if (thread_->IsWakeUpPending()) |
| 265 return nullptr; | 278 return nullptr; |
| 266 | 279 |
| 267 // Call OnDetach() within the scope of |thread_lock_| to prevent the delegate | 280 // Call OnDetach() within the scope of |thread_lock_| to prevent the delegate |
| 268 // from being used concurrently from an old and a new thread. | 281 // from being used concurrently from an old and a new thread. |
| 269 delegate_->OnDetach(); | 282 delegate_->OnDetach(); |
| 270 | 283 |
| 271 return std::move(thread_); | 284 return std::move(thread_); |
| 272 } | 285 } |
| 273 | 286 |
| 274 void SchedulerWorker::CreateThread() { | 287 void SchedulerWorker::CreateThread() { |
| 275 thread_ = Thread::Create(this); | 288 thread_ = Thread::Create(this); |
| 276 } | 289 } |
| 277 | 290 |
| 278 void SchedulerWorker::CreateThreadAssertSynchronized() { | 291 void SchedulerWorker::CreateThreadAssertSynchronized() { |
| 279 thread_lock_.AssertAcquired(); | 292 thread_lock_.AssertAcquired(); |
| 280 CreateThread(); | 293 CreateThread(); |
| 281 } | 294 } |
| 282 | 295 |
| 283 } // namespace internal | 296 } // namespace internal |
| 284 } // namespace base | 297 } // namespace base |
| OLD | NEW |