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 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 if (thread_) | 222 if (thread_) |
| 223 thread_->WakeUp(); | 223 thread_->WakeUp(); |
| 224 } | 224 } |
| 225 | 225 |
| 226 void SchedulerWorker::JoinForTesting() { | 226 void SchedulerWorker::JoinForTesting() { |
| 227 DCHECK(!should_exit_for_testing_.IsSet()); | 227 DCHECK(!should_exit_for_testing_.IsSet()); |
| 228 should_exit_for_testing_.Set(); | 228 should_exit_for_testing_.Set(); |
| 229 | 229 |
| 230 WakeUp(); | 230 WakeUp(); |
| 231 | 231 |
| 232 // Normally holding a lock and joining is dangerous. However, since this is | 232 std::unique_ptr<Thread> thread; |
| 233 // only for testing, we're okay since the only scenario that could impact this | |
| 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 | 233 |
| 240 thread_.reset(); | 234 { |
| 235 // Take ownership of |thread_|. This prevents it from detaching. | |
| 236 AutoSchedulerLock auto_lock(thread_lock_); | |
| 237 thread = std::move(thread_); | |
| 238 } | |
| 239 | |
| 240 // Join outside the lock. | |
|
robliao
2017/01/17 19:01:27
Nit: Remove this comment as it is self evident.
fdoray
2017/01/17 20:43:13
Done.
| |
| 241 if (thread) | |
| 242 thread->Join(); | |
|
robliao
2017/01/17 19:01:27
Previously, JoinForTesting holding the lock would
fdoray
2017/01/17 20:43:13
Done.
| |
| 241 } | 243 } |
| 242 | 244 |
| 243 bool SchedulerWorker::ThreadAliveForTesting() const { | 245 bool SchedulerWorker::ThreadAliveForTesting() const { |
| 244 AutoSchedulerLock auto_lock(thread_lock_); | 246 AutoSchedulerLock auto_lock(thread_lock_); |
| 245 return !!thread_; | 247 return !!thread_; |
| 246 } | 248 } |
| 247 | 249 |
| 248 SchedulerWorker::SchedulerWorker(ThreadPriority priority_hint, | 250 SchedulerWorker::SchedulerWorker(ThreadPriority priority_hint, |
| 249 std::unique_ptr<Delegate> delegate, | 251 std::unique_ptr<Delegate> delegate, |
| 250 TaskTracker* task_tracker) | 252 TaskTracker* task_tracker) |
| 251 : priority_hint_(priority_hint), | 253 : priority_hint_(priority_hint), |
| 252 delegate_(std::move(delegate)), | 254 delegate_(std::move(delegate)), |
| 253 task_tracker_(task_tracker) { | 255 task_tracker_(task_tracker) { |
| 254 DCHECK(delegate_); | 256 DCHECK(delegate_); |
| 255 DCHECK(task_tracker_); | 257 DCHECK(task_tracker_); |
| 256 } | 258 } |
| 257 | 259 |
| 258 std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::Detach() { | 260 std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::Detach() { |
| 259 DCHECK(!should_exit_for_testing_.IsSet()) << "Worker was already joined"; | |
| 260 AutoSchedulerLock auto_lock(thread_lock_); | 261 AutoSchedulerLock auto_lock(thread_lock_); |
| 262 | |
| 263 // Do not detach if the thread is being joined. | |
| 264 if (!thread_) { | |
| 265 DCHECK(should_exit_for_testing_.IsSet()); | |
| 266 return nullptr; | |
| 267 } | |
| 268 | |
| 261 // If a wakeup is pending, then a WakeUp() came in while we were deciding to | 269 // 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 | 270 // detach. This means we can't go away anymore since we would break the |
| 263 // guarantee that we call GetWork() after a successful wakeup. | 271 // guarantee that we call GetWork() after a successful wakeup. |
| 264 if (thread_->IsWakeUpPending()) | 272 if (thread_->IsWakeUpPending()) |
| 265 return nullptr; | 273 return nullptr; |
| 266 | 274 |
| 267 // Call OnDetach() within the scope of |thread_lock_| to prevent the delegate | 275 // Call OnDetach() within the scope of |thread_lock_| to prevent the delegate |
| 268 // from being used concurrently from an old and a new thread. | 276 // from being used concurrently from an old and a new thread. |
| 269 delegate_->OnDetach(); | 277 delegate_->OnDetach(); |
| 270 | 278 |
| 271 return std::move(thread_); | 279 return std::move(thread_); |
| 272 } | 280 } |
| 273 | 281 |
| 274 void SchedulerWorker::CreateThread() { | 282 void SchedulerWorker::CreateThread() { |
| 275 thread_ = Thread::Create(this); | 283 thread_ = Thread::Create(this); |
| 276 } | 284 } |
| 277 | 285 |
| 278 void SchedulerWorker::CreateThreadAssertSynchronized() { | 286 void SchedulerWorker::CreateThreadAssertSynchronized() { |
| 279 thread_lock_.AssertAcquired(); | 287 thread_lock_.AssertAcquired(); |
| 280 CreateThread(); | 288 CreateThread(); |
| 281 } | 289 } |
| 282 | 290 |
| 283 } // namespace internal | 291 } // namespace internal |
| 284 } // namespace base | 292 } // namespace base |
| OLD | NEW |