Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: base/task_scheduler/scheduler_worker.cc

Issue 2628313004: Add TaskScheduler::JoinForTesting(). (Closed)
Patch Set: self-review Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 // Make sure the thread is awake. It will see that
240 // |should_exit_for_testing_| is set and exit shortly after.
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
OLDNEW
« no previous file with comments | « base/task_scheduler/scheduler_worker.h ('k') | base/task_scheduler/scheduler_worker_pool_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698