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

Side by Side Diff: base/threading/sequenced_worker_pool.cc

Issue 9651026: Clean up condition variable usage in SequencedWorkerPool (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address nits Created 8 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/threading/sequenced_worker_pool.h" 5 #include "base/threading/sequenced_worker_pool.h"
6 6
7 #include <list> 7 #include <list>
8 #include <map> 8 #include <map>
9 #include <set> 9 #include <set>
10 #include <utility> 10 #include <utility>
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 bool PostTask(const std::string* optional_token_name, 86 bool PostTask(const std::string* optional_token_name,
87 SequenceToken sequence_token, 87 SequenceToken sequence_token,
88 WorkerShutdown shutdown_behavior, 88 WorkerShutdown shutdown_behavior,
89 const tracked_objects::Location& from_here, 89 const tracked_objects::Location& from_here,
90 const Closure& task); 90 const Closure& task);
91 91
92 bool RunsTasksOnCurrentThread() const; 92 bool RunsTasksOnCurrentThread() const;
93 93
94 void FlushForTesting(); 94 void FlushForTesting();
95 95
96 void TriggerSpuriousWorkSignalForTesting();
97
98 int GetWorkSignalCountForTesting() const;
99
96 void Shutdown(); 100 void Shutdown();
97 101
98 void SetTestingObserver(TestingObserver* observer); 102 void SetTestingObserver(TestingObserver* observer);
99 103
100 // Runs the worker loop on the background thread. 104 // Runs the worker loop on the background thread.
101 void ThreadLoop(Worker* this_worker); 105 void ThreadLoop(Worker* this_worker);
102 106
103 private: 107 private:
108 // Returns whether there are no more pending tasks and all threads
109 // are idle. Must be called under lock.
110 bool IsIdle() const;
111
104 // Called from within the lock, this converts the given token name into a 112 // Called from within the lock, this converts the given token name into a
105 // token ID, creating a new one if necessary. 113 // token ID, creating a new one if necessary.
106 int LockedGetNamedTokenID(const std::string& name); 114 int LockedGetNamedTokenID(const std::string& name);
107 115
108 // The calling code should clear the given delete_these_oustide_lock 116 // The calling code should clear the given delete_these_oustide_lock
109 // vector the next time the lock is released. See the implementation for 117 // vector the next time the lock is released. See the implementation for
110 // a more detailed description. 118 // a more detailed description.
111 bool GetWork(SequencedTask* task, 119 bool GetWork(SequencedTask* task,
112 std::vector<Closure>* delete_these_outside_lock); 120 std::vector<Closure>* delete_these_outside_lock);
113 121
(...skipping 21 matching lines...) Expand all
135 // 143 //
136 // See the implementedion for more. 144 // See the implementedion for more.
137 int PrepareToStartAdditionalThreadIfHelpful(); 145 int PrepareToStartAdditionalThreadIfHelpful();
138 146
139 // The second part of thread creation after 147 // The second part of thread creation after
140 // PrepareToStartAdditionalThreadIfHelpful with the thread number it 148 // PrepareToStartAdditionalThreadIfHelpful with the thread number it
141 // generated. This actually creates the thread and should be called outside 149 // generated. This actually creates the thread and should be called outside
142 // the lock to avoid blocking important work starting a thread in the lock. 150 // the lock to avoid blocking important work starting a thread in the lock.
143 void FinishStartingAdditionalThread(int thread_number); 151 void FinishStartingAdditionalThread(int thread_number);
144 152
153 // Signal |has_work_| and increment |has_work_signal_count_|.
154 void SignalHasWork();
155
145 // Checks whether there is work left that's blocking shutdown. Must be 156 // Checks whether there is work left that's blocking shutdown. Must be
146 // called inside the lock. 157 // called inside the lock.
147 bool CanShutdown() const; 158 bool CanShutdown() const;
148 159
149 SequencedWorkerPool* const worker_pool_; 160 SequencedWorkerPool* const worker_pool_;
150 161
151 // The last sequence number used. Managed by GetSequenceToken, since this 162 // The last sequence number used. Managed by GetSequenceToken, since this
152 // only does threadsafe increment operations, you do not need to hold the 163 // only does threadsafe increment operations, you do not need to hold the
153 // lock. 164 // lock.
154 volatile subtle::Atomic32 last_sequence_number_; 165 volatile subtle::Atomic32 last_sequence_number_;
155 166
156 // This lock protects |everything in this class|. Do not read or modify 167 // This lock protects |everything in this class|. Do not read or modify
157 // anything without holding this lock. Do not block while holding this 168 // anything without holding this lock. Do not block while holding this
158 // lock. 169 // lock.
159 mutable Lock lock_; 170 mutable Lock lock_;
160 171
161 // Condition variable used to wake up worker threads when a task is runnable. 172 // Condition variable that is waited on by worker threads until new
162 ConditionVariable cond_var_; 173 // tasks are posted or shutdown starts.
174 ConditionVariable has_work_cv_;
175
176 // Number of times |has_work_| has been signalled. Used for testing.
177 int has_work_signal_count_;
178
179 // Condition variable that is waited on by non-worker threads (in
180 // FlushForTesting()) until IsIdle() goes to true.
181 ConditionVariable is_idle_cv_;
182
183 // Condition variable that is waited on by non-worker threads (in
184 // Shutdown()) until CanShutdown() goes to true.
185 ConditionVariable can_shutdown_cv_;
163 186
164 // The maximum number of worker threads we'll create. 187 // The maximum number of worker threads we'll create.
165 const size_t max_threads_; 188 const size_t max_threads_;
166 189
167 const std::string thread_name_prefix_; 190 const std::string thread_name_prefix_;
168 191
169 // Associates all known sequence token names with their IDs. 192 // Associates all known sequence token names with their IDs.
170 std::map<std::string, int> named_sequence_tokens_; 193 std::map<std::string, int> named_sequence_tokens_;
171 194
172 // Owning pointers to all threads we've created so far, indexed by 195 // Owning pointers to all threads we've created so far, indexed by
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 261
239 // Inner definitions --------------------------------------------------------- 262 // Inner definitions ---------------------------------------------------------
240 263
241 SequencedWorkerPool::Inner::Inner( 264 SequencedWorkerPool::Inner::Inner(
242 SequencedWorkerPool* worker_pool, 265 SequencedWorkerPool* worker_pool,
243 size_t max_threads, 266 size_t max_threads,
244 const std::string& thread_name_prefix) 267 const std::string& thread_name_prefix)
245 : worker_pool_(worker_pool), 268 : worker_pool_(worker_pool),
246 last_sequence_number_(0), 269 last_sequence_number_(0),
247 lock_(), 270 lock_(),
248 cond_var_(&lock_), 271 has_work_cv_(&lock_),
272 has_work_signal_count_(0),
273 is_idle_cv_(&lock_),
274 can_shutdown_cv_(&lock_),
249 max_threads_(max_threads), 275 max_threads_(max_threads),
250 thread_name_prefix_(thread_name_prefix), 276 thread_name_prefix_(thread_name_prefix),
251 thread_being_created_(false), 277 thread_being_created_(false),
252 waiting_thread_count_(0), 278 waiting_thread_count_(0),
253 blocking_shutdown_thread_count_(0), 279 blocking_shutdown_thread_count_(0),
254 pending_task_count_(0), 280 pending_task_count_(0),
255 blocking_shutdown_pending_task_count_(0), 281 blocking_shutdown_pending_task_count_(0),
256 shutdown_called_(false), 282 shutdown_called_(false),
257 testing_observer_(NULL) {} 283 testing_observer_(NULL) {}
258 284
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 blocking_shutdown_pending_task_count_++; 337 blocking_shutdown_pending_task_count_++;
312 338
313 create_thread_id = PrepareToStartAdditionalThreadIfHelpful(); 339 create_thread_id = PrepareToStartAdditionalThreadIfHelpful();
314 } 340 }
315 341
316 // Actually start the additional thread or signal an existing one now that 342 // Actually start the additional thread or signal an existing one now that
317 // we're outside the lock. 343 // we're outside the lock.
318 if (create_thread_id) 344 if (create_thread_id)
319 FinishStartingAdditionalThread(create_thread_id); 345 FinishStartingAdditionalThread(create_thread_id);
320 else 346 else
321 cond_var_.Signal(); 347 SignalHasWork();
322 348
323 return true; 349 return true;
324 } 350 }
325 351
326 bool SequencedWorkerPool::Inner::RunsTasksOnCurrentThread() const { 352 bool SequencedWorkerPool::Inner::RunsTasksOnCurrentThread() const {
327 AutoLock lock(lock_); 353 AutoLock lock(lock_);
328 return ContainsKey(threads_, PlatformThread::CurrentId()); 354 return ContainsKey(threads_, PlatformThread::CurrentId());
329 } 355 }
330 356
331 void SequencedWorkerPool::Inner::FlushForTesting() { 357 void SequencedWorkerPool::Inner::FlushForTesting() {
332 { 358 AutoLock lock(lock_);
333 AutoLock lock(lock_); 359 while (!IsIdle())
334 while (pending_task_count_ > 0 || waiting_thread_count_ < threads_.size()) 360 is_idle_cv_.Wait();
335 cond_var_.Wait(); 361 }
336 } 362
337 cond_var_.Signal(); 363 void SequencedWorkerPool::Inner::TriggerSpuriousWorkSignalForTesting() {
364 SignalHasWork();
365 }
366
367 int SequencedWorkerPool::Inner::GetWorkSignalCountForTesting() const {
368 AutoLock lock(lock_);
369 return has_work_signal_count_;
338 } 370 }
339 371
340 void SequencedWorkerPool::Inner::Shutdown() { 372 void SequencedWorkerPool::Inner::Shutdown() {
341 // Mark us as terminated and go through and drop all tasks that aren't 373 // Mark us as terminated and go through and drop all tasks that aren't
342 // required to run on shutdown. Since no new tasks will get posted once the 374 // required to run on shutdown. Since no new tasks will get posted once the
343 // terminated flag is set, this ensures that all remaining tasks are required 375 // terminated flag is set, this ensures that all remaining tasks are required
344 // for shutdown whenever the termianted_ flag is set. 376 // for shutdown whenever the termianted_ flag is set.
345 { 377 {
346 AutoLock lock(lock_); 378 AutoLock lock(lock_);
347 379
348 if (shutdown_called_) 380 if (shutdown_called_)
349 return; 381 return;
350 shutdown_called_ = true; 382 shutdown_called_ = true;
351 383
352 // Tickle the threads. This will wake up a waiting one so it will know that 384 // Tickle the threads. This will wake up a waiting one so it will know that
353 // it can exit, which in turn will wake up any other waiting ones. 385 // it can exit, which in turn will wake up any other waiting ones.
354 cond_var_.Signal(); 386 has_work_cv_.Signal();
355 387
356 // There are no pending or running tasks blocking shutdown, we're done. 388 // There are no pending or running tasks blocking shutdown, we're done.
357 if (CanShutdown()) 389 if (CanShutdown())
358 return; 390 return;
359 } 391 }
360 392
361 // If we get here, we know we're either waiting on a blocking task that's 393 // If we're here, then something is blocking shutdown. So wait for
362 // currently running, waiting on a blocking task that hasn't been scheduled 394 // CanShutdown() to go to true.
363 // yet, or both. Block on the "queue empty" event to know when all tasks are 395
364 // complete. This must be done outside the lock.
365 if (testing_observer_) 396 if (testing_observer_)
366 testing_observer_->WillWaitForShutdown(); 397 testing_observer_->WillWaitForShutdown();
367 398
368 TimeTicks shutdown_wait_begin = TimeTicks::Now(); 399 TimeTicks shutdown_wait_begin = TimeTicks::Now();
369 400
370 // Wait for no more tasks.
371 { 401 {
372 AutoLock lock(lock_); 402 AutoLock lock(lock_);
373 while (!CanShutdown()) 403 while (!CanShutdown())
374 cond_var_.Wait(); 404 can_shutdown_cv_.Wait();
375 } 405 }
376 UMA_HISTOGRAM_TIMES("SequencedWorkerPool.ShutdownDelayTime", 406 UMA_HISTOGRAM_TIMES("SequencedWorkerPool.ShutdownDelayTime",
377 TimeTicks::Now() - shutdown_wait_begin); 407 TimeTicks::Now() - shutdown_wait_begin);
378 } 408 }
379 409
380 void SequencedWorkerPool::Inner::SetTestingObserver( 410 void SequencedWorkerPool::Inner::SetTestingObserver(
381 TestingObserver* observer) { 411 TestingObserver* observer) {
382 AutoLock lock(lock_); 412 AutoLock lock(lock_);
383 testing_observer_ = observer; 413 testing_observer_ = observer;
384 } 414 }
385 415
386 void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) { 416 void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) {
387 { 417 {
388 AutoLock lock(lock_); 418 AutoLock lock(lock_);
389 DCHECK(thread_being_created_); 419 DCHECK(thread_being_created_);
390 thread_being_created_ = false; 420 thread_being_created_ = false;
391 std::pair<ThreadMap::iterator, bool> result = 421 std::pair<ThreadMap::iterator, bool> result =
392 threads_.insert( 422 threads_.insert(
393 std::make_pair(this_worker->tid(), make_linked_ptr(this_worker))); 423 std::make_pair(this_worker->tid(), make_linked_ptr(this_worker)));
394 DCHECK(result.second); 424 DCHECK(result.second);
395 425
396 while (true) { 426 while (true) {
397 // See GetWork for what delete_these_outside_lock is doing. 427 // See GetWork for what delete_these_outside_lock is doing.
398 SequencedTask task; 428 SequencedTask task;
399 std::vector<Closure> delete_these_outside_lock; 429 std::vector<Closure> delete_these_outside_lock;
400 if (GetWork(&task, &delete_these_outside_lock)) { 430 if (GetWork(&task, &delete_these_outside_lock)) {
401 int new_thread_id = WillRunWorkerTask(task); 431 int new_thread_id = WillRunWorkerTask(task);
402 { 432 {
403 AutoUnlock unlock(lock_); 433 AutoUnlock unlock(lock_);
404 cond_var_.Signal(); 434 // There may be more work available, so wake up another
435 // worker thread. (Technically not required, since we
436 // already get a signal for each new task, but it doesn't
437 // hurt.)
438 has_work_cv_.Signal();
405 delete_these_outside_lock.clear(); 439 delete_these_outside_lock.clear();
406 440
407 // Complete thread creation outside the lock if necessary. 441 // Complete thread creation outside the lock if necessary.
408 if (new_thread_id) 442 if (new_thread_id)
409 FinishStartingAdditionalThread(new_thread_id); 443 FinishStartingAdditionalThread(new_thread_id);
410 444
411 task.task.Run(); 445 task.task.Run();
412 446
413 // Make sure our task is erased outside the lock for the same reason 447 // Make sure our task is erased outside the lock for the same reason
414 // we do this with delete_these_oustide_lock. 448 // we do this with delete_these_oustide_lock.
415 task.task = Closure(); 449 task.task = Closure();
416 } 450 }
417 DidRunWorkerTask(task); // Must be done inside the lock. 451 DidRunWorkerTask(task); // Must be done inside the lock.
418 } else { 452 } else {
419 // When we're terminating and there's no more work, we can 453 // When we're terminating and there's no more work, we can
420 // shut down. You can't get more tasks posted once 454 // shut down. You can't get more tasks posted once
421 // shutdown_called_ is set. There may be some tasks stuck 455 // shutdown_called_ is set. There may be some tasks stuck
422 // behind running ones with the same sequence token, but 456 // behind running ones with the same sequence token, but
423 // additional threads won't help this case. 457 // additional threads won't help this case.
424 if (shutdown_called_) 458 if (shutdown_called_)
425 break; 459 break;
426 waiting_thread_count_++; 460 waiting_thread_count_++;
427 cond_var_.Signal(); // For Flush() that may be waiting on the 461 // This is the only time that IsIdle() can go to true.
428 // waiting thread count to go up. 462 if (IsIdle())
429 cond_var_.Wait(); 463 is_idle_cv_.Signal();
464 has_work_cv_.Wait();
430 waiting_thread_count_--; 465 waiting_thread_count_--;
431 } 466 }
432 } 467 }
433 } 468 } // Release lock_.
434 469
435 // We noticed we should exit. Wake up the next worker so it knows it should 470 // We noticed we should exit. Wake up the next worker so it knows it should
436 // exit as well (because the Shutdown() code only signals once). 471 // exit as well (because the Shutdown() code only signals once).
437 cond_var_.Signal(); 472 has_work_cv_.Signal();
473
474 // Possibly unblock shutdown.
475 can_shutdown_cv_.Signal();
476 }
477
478 bool SequencedWorkerPool::Inner::IsIdle() const {
479 lock_.AssertAcquired();
480 return pending_task_count_ == 0 && waiting_thread_count_ == threads_.size();
438 } 481 }
439 482
440 int SequencedWorkerPool::Inner::LockedGetNamedTokenID( 483 int SequencedWorkerPool::Inner::LockedGetNamedTokenID(
441 const std::string& name) { 484 const std::string& name) {
442 lock_.AssertAcquired(); 485 lock_.AssertAcquired();
443 DCHECK(!name.empty()); 486 DCHECK(!name.empty());
444 487
445 std::map<std::string, int>::const_iterator found = 488 std::map<std::string, int>::const_iterator found =
446 named_sequence_tokens_.find(name); 489 named_sequence_tokens_.find(name);
447 if (found != named_sequence_tokens_.end()) 490 if (found != named_sequence_tokens_.end())
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 // vector they passed to us once the lock is exited to make this 554 // vector they passed to us once the lock is exited to make this
512 // happen. 555 // happen.
513 delete_these_outside_lock->push_back(i->task); 556 delete_these_outside_lock->push_back(i->task);
514 i = pending_tasks_.erase(i); 557 i = pending_tasks_.erase(i);
515 pending_task_count_--; 558 pending_task_count_--;
516 } else { 559 } else {
517 // Found a runnable task. 560 // Found a runnable task.
518 *task = *i; 561 *task = *i;
519 i = pending_tasks_.erase(i); 562 i = pending_tasks_.erase(i);
520 pending_task_count_--; 563 pending_task_count_--;
521 if (task->shutdown_behavior == BLOCK_SHUTDOWN) 564 if (task->shutdown_behavior == BLOCK_SHUTDOWN) {
522 blocking_shutdown_pending_task_count_--; 565 blocking_shutdown_pending_task_count_--;
566 }
523 567
524 found_task = true; 568 found_task = true;
525 break; 569 break;
526 } 570 }
527 } 571 }
528 572
529 // Track the number of tasks we had to skip over to see if we should be 573 // Track the number of tasks we had to skip over to see if we should be
530 // making this more efficient. If this number ever becomes large or is 574 // making this more efficient. If this number ever becomes large or is
531 // frequently "some", we should consider the optimization above. 575 // frequently "some", we should consider the optimization above.
532 UMA_HISTOGRAM_COUNTS_100("SequencedWorkerPool.UnrunnableTaskCount", 576 UMA_HISTOGRAM_COUNTS_100("SequencedWorkerPool.UnrunnableTaskCount",
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 void SequencedWorkerPool::Inner::FinishStartingAdditionalThread( 677 void SequencedWorkerPool::Inner::FinishStartingAdditionalThread(
634 int thread_number) { 678 int thread_number) {
635 // Called outside of the lock. 679 // Called outside of the lock.
636 DCHECK(thread_number > 0); 680 DCHECK(thread_number > 0);
637 681
638 // The worker is assigned to the list when the thread actually starts, which 682 // The worker is assigned to the list when the thread actually starts, which
639 // will manage the memory of the pointer. 683 // will manage the memory of the pointer.
640 new Worker(worker_pool_, thread_number, thread_name_prefix_); 684 new Worker(worker_pool_, thread_number, thread_name_prefix_);
641 } 685 }
642 686
687 void SequencedWorkerPool::Inner::SignalHasWork() {
688 has_work_cv_.Signal();
689 {
690 AutoLock lock(lock_);
691 ++has_work_signal_count_;
692 }
693 }
694
643 bool SequencedWorkerPool::Inner::CanShutdown() const { 695 bool SequencedWorkerPool::Inner::CanShutdown() const {
644 lock_.AssertAcquired(); 696 lock_.AssertAcquired();
645 // See PrepareToStartAdditionalThreadIfHelpful for how thread creation works. 697 // See PrepareToStartAdditionalThreadIfHelpful for how thread creation works.
646 return !thread_being_created_ && 698 return !thread_being_created_ &&
647 blocking_shutdown_thread_count_ == 0 && 699 blocking_shutdown_thread_count_ == 0 &&
648 blocking_shutdown_pending_task_count_ == 0; 700 blocking_shutdown_pending_task_count_ == 0;
649 } 701 }
650 702
651 // SequencedWorkerPool -------------------------------------------------------- 703 // SequencedWorkerPool --------------------------------------------------------
652 704
653 SequencedWorkerPool::SequencedWorkerPool( 705 SequencedWorkerPool::SequencedWorkerPool(
654 size_t max_threads, 706 size_t max_threads,
655 const std::string& thread_name_prefix) 707 const std::string& thread_name_prefix)
656 : constructor_message_loop_(MessageLoopProxy::current()), 708 : constructor_message_loop_(MessageLoopProxy::current()),
657 inner_(new Inner(ALLOW_THIS_IN_INITIALIZER_LIST(this), 709 inner_(new Inner(ALLOW_THIS_IN_INITIALIZER_LIST(this),
658 max_threads, thread_name_prefix)) { 710 max_threads, thread_name_prefix)) {
659 DCHECK(constructor_message_loop_.get()); 711 DCHECK(constructor_message_loop_.get());
660 } 712 }
661 713
662 SequencedWorkerPool::~SequencedWorkerPool() {} 714 SequencedWorkerPool::~SequencedWorkerPool() {}
663 715
664 void SequencedWorkerPool::OnDestruct() const { 716 void SequencedWorkerPool::OnDestruct() const {
665 // TODO(akalin): Once we can easily check if we're on a worker 717 // TODO(akalin): Once we can easily check if we're on a worker
666 // thread or not, use that instead of restricting destruction to 718 // thread or not, use that instead of restricting destruction to
667 // only the constructor message loop. 719 // only the constructor message loop.
668 if (constructor_message_loop_->BelongsToCurrentThread()) { 720 if (constructor_message_loop_->BelongsToCurrentThread())
669 delete this; 721 delete this;
670 } else { 722 else
671 constructor_message_loop_->DeleteSoon(FROM_HERE, this); 723 constructor_message_loop_->DeleteSoon(FROM_HERE, this);
672 }
673 } 724 }
674 725
675 SequencedWorkerPool::SequenceToken SequencedWorkerPool::GetSequenceToken() { 726 SequencedWorkerPool::SequenceToken SequencedWorkerPool::GetSequenceToken() {
676 return inner_->GetSequenceToken(); 727 return inner_->GetSequenceToken();
677 } 728 }
678 729
679 SequencedWorkerPool::SequenceToken SequencedWorkerPool::GetNamedSequenceToken( 730 SequencedWorkerPool::SequenceToken SequencedWorkerPool::GetNamedSequenceToken(
680 const std::string& name) { 731 const std::string& name) {
681 return inner_->GetNamedSequenceToken(name); 732 return inner_->GetNamedSequenceToken(name);
682 } 733 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 } 792 }
742 793
743 bool SequencedWorkerPool::RunsTasksOnCurrentThread() const { 794 bool SequencedWorkerPool::RunsTasksOnCurrentThread() const {
744 return inner_->RunsTasksOnCurrentThread(); 795 return inner_->RunsTasksOnCurrentThread();
745 } 796 }
746 797
747 void SequencedWorkerPool::FlushForTesting() { 798 void SequencedWorkerPool::FlushForTesting() {
748 inner_->FlushForTesting(); 799 inner_->FlushForTesting();
749 } 800 }
750 801
802 void SequencedWorkerPool::TriggerSpuriousWorkSignalForTesting() {
803 inner_->TriggerSpuriousWorkSignalForTesting();
804 }
805
806 int SequencedWorkerPool::GetWorkSignalCountForTesting() const {
807 return inner_->GetWorkSignalCountForTesting();
808 }
809
751 void SequencedWorkerPool::Shutdown() { 810 void SequencedWorkerPool::Shutdown() {
811 DCHECK(constructor_message_loop_->BelongsToCurrentThread());
752 inner_->Shutdown(); 812 inner_->Shutdown();
753 } 813 }
754 814
755 void SequencedWorkerPool::SetTestingObserver(TestingObserver* observer) { 815 void SequencedWorkerPool::SetTestingObserver(TestingObserver* observer) {
756 inner_->SetTestingObserver(observer); 816 inner_->SetTestingObserver(observer);
757 } 817 }
758 818
759 } // namespace base 819 } // namespace base
OLDNEW
« no previous file with comments | « base/threading/sequenced_worker_pool.h ('k') | base/threading/sequenced_worker_pool_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698