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

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 jar's comments 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 signalled whenever a new task is
162 ConditionVariable cond_var_; 173 // posted or when Shutdown() is called.
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 signalled whenever IsIdle() goes to
180 // true.
181 ConditionVariable is_idle_cv_;
182
183 // Condition variable that is signalled whwnever CanShutdown() goes
184 // 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 {
jar (doing other things) 2012/03/12 19:42:36 nit: It bugs me a little that we've added this mus
akalin 2012/03/12 20:42:16 I think I can remove this variable and instead add
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.
436 has_work_cv_.Signal();
405 delete_these_outside_lock.clear(); 437 delete_these_outside_lock.clear();
406 438
407 // Complete thread creation outside the lock if necessary. 439 // Complete thread creation outside the lock if necessary.
408 if (new_thread_id) 440 if (new_thread_id)
409 FinishStartingAdditionalThread(new_thread_id); 441 FinishStartingAdditionalThread(new_thread_id);
410 442
411 task.task.Run(); 443 task.task.Run();
412 444
413 // Make sure our task is erased outside the lock for the same reason 445 // Make sure our task is erased outside the lock for the same reason
414 // we do this with delete_these_oustide_lock. 446 // we do this with delete_these_oustide_lock.
415 task.task = Closure(); 447 task.task = Closure();
416 } 448 }
417 DidRunWorkerTask(task); // Must be done inside the lock. 449 DidRunWorkerTask(task); // Must be done inside the lock.
418 } else { 450 } else {
419 // When we're terminating and there's no more work, we can 451 // When we're terminating and there's no more work, we can
420 // shut down. You can't get more tasks posted once 452 // shut down. You can't get more tasks posted once
421 // shutdown_called_ is set. There may be some tasks stuck 453 // shutdown_called_ is set. There may be some tasks stuck
422 // behind running ones with the same sequence token, but 454 // behind running ones with the same sequence token, but
423 // additional threads won't help this case. 455 // additional threads won't help this case.
424 if (shutdown_called_) 456 if (shutdown_called_)
425 break; 457 break;
426 waiting_thread_count_++; 458 waiting_thread_count_++;
427 cond_var_.Signal(); // For Flush() that may be waiting on the 459 // This is the only time that IsIdle() can go to true.
428 // waiting thread count to go up. 460 if (IsIdle())
429 cond_var_.Wait(); 461 is_idle_cv_.Signal();
462 has_work_cv_.Wait();
430 waiting_thread_count_--; 463 waiting_thread_count_--;
431 } 464 }
432 } 465 }
466
467 // Unblock shutdown if possible.
468 if (CanShutdown())
469 can_shutdown_cv_.Signal();
jar (doing other things) 2012/03/12 19:42:36 Placing this here is probably more optimal than I
akalin 2012/03/12 20:42:16 Yeah, I think that's simpler. I moved it out.
433 } 470 }
jar (doing other things) 2012/03/12 19:42:36 nit: Add comment: // Release lock_.
akalin 2012/03/12 20:42:16 Done.
434 471
435 // We noticed we should exit. Wake up the next worker so it knows it should 472 // 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). 473 // exit as well (because the Shutdown() code only signals once).
437 cond_var_.Signal(); 474 has_work_cv_.Signal();
475 }
476
477 bool SequencedWorkerPool::Inner::IsIdle() const {
478 lock_.AssertAcquired();
479 return pending_task_count_ == 0 && waiting_thread_count_ == threads_.size();
438 } 480 }
439 481
440 int SequencedWorkerPool::Inner::LockedGetNamedTokenID( 482 int SequencedWorkerPool::Inner::LockedGetNamedTokenID(
441 const std::string& name) { 483 const std::string& name) {
442 lock_.AssertAcquired(); 484 lock_.AssertAcquired();
443 DCHECK(!name.empty()); 485 DCHECK(!name.empty());
444 486
445 std::map<std::string, int>::const_iterator found = 487 std::map<std::string, int>::const_iterator found =
446 named_sequence_tokens_.find(name); 488 named_sequence_tokens_.find(name);
447 if (found != named_sequence_tokens_.end()) 489 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 553 // vector they passed to us once the lock is exited to make this
512 // happen. 554 // happen.
513 delete_these_outside_lock->push_back(i->task); 555 delete_these_outside_lock->push_back(i->task);
514 i = pending_tasks_.erase(i); 556 i = pending_tasks_.erase(i);
515 pending_task_count_--; 557 pending_task_count_--;
516 } else { 558 } else {
517 // Found a runnable task. 559 // Found a runnable task.
518 *task = *i; 560 *task = *i;
519 i = pending_tasks_.erase(i); 561 i = pending_tasks_.erase(i);
520 pending_task_count_--; 562 pending_task_count_--;
521 if (task->shutdown_behavior == BLOCK_SHUTDOWN) 563 if (task->shutdown_behavior == BLOCK_SHUTDOWN) {
522 blocking_shutdown_pending_task_count_--; 564 blocking_shutdown_pending_task_count_--;
565 }
523 566
524 found_task = true; 567 found_task = true;
525 break; 568 break;
526 } 569 }
527 } 570 }
528 571
529 // Track the number of tasks we had to skip over to see if we should be 572 // 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 573 // making this more efficient. If this number ever becomes large or is
531 // frequently "some", we should consider the optimization above. 574 // frequently "some", we should consider the optimization above.
532 UMA_HISTOGRAM_COUNTS_100("SequencedWorkerPool.UnrunnableTaskCount", 575 UMA_HISTOGRAM_COUNTS_100("SequencedWorkerPool.UnrunnableTaskCount",
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 void SequencedWorkerPool::Inner::FinishStartingAdditionalThread( 676 void SequencedWorkerPool::Inner::FinishStartingAdditionalThread(
634 int thread_number) { 677 int thread_number) {
635 // Called outside of the lock. 678 // Called outside of the lock.
636 DCHECK(thread_number > 0); 679 DCHECK(thread_number > 0);
637 680
638 // The worker is assigned to the list when the thread actually starts, which 681 // The worker is assigned to the list when the thread actually starts, which
639 // will manage the memory of the pointer. 682 // will manage the memory of the pointer.
640 new Worker(worker_pool_, thread_number, thread_name_prefix_); 683 new Worker(worker_pool_, thread_number, thread_name_prefix_);
641 } 684 }
642 685
686 void SequencedWorkerPool::Inner::SignalHasWork() {
687 has_work_cv_.Signal();
688 {
689 AutoLock lock(lock_);
690 ++has_work_signal_count_;
691 }
692 }
693
643 bool SequencedWorkerPool::Inner::CanShutdown() const { 694 bool SequencedWorkerPool::Inner::CanShutdown() const {
644 lock_.AssertAcquired(); 695 lock_.AssertAcquired();
645 // See PrepareToStartAdditionalThreadIfHelpful for how thread creation works. 696 // See PrepareToStartAdditionalThreadIfHelpful for how thread creation works.
646 return !thread_being_created_ && 697 return !thread_being_created_ &&
647 blocking_shutdown_thread_count_ == 0 && 698 blocking_shutdown_thread_count_ == 0 &&
648 blocking_shutdown_pending_task_count_ == 0; 699 blocking_shutdown_pending_task_count_ == 0;
649 } 700 }
650 701
651 // SequencedWorkerPool -------------------------------------------------------- 702 // SequencedWorkerPool --------------------------------------------------------
652 703
653 SequencedWorkerPool::SequencedWorkerPool( 704 SequencedWorkerPool::SequencedWorkerPool(
654 size_t max_threads, 705 size_t max_threads,
655 const std::string& thread_name_prefix) 706 const std::string& thread_name_prefix)
656 : constructor_message_loop_(MessageLoopProxy::current()), 707 : constructor_message_loop_(MessageLoopProxy::current()),
657 inner_(new Inner(ALLOW_THIS_IN_INITIALIZER_LIST(this), 708 inner_(new Inner(ALLOW_THIS_IN_INITIALIZER_LIST(this),
658 max_threads, thread_name_prefix)) { 709 max_threads, thread_name_prefix)) {
659 DCHECK(constructor_message_loop_.get()); 710 DCHECK(constructor_message_loop_.get());
660 } 711 }
661 712
662 SequencedWorkerPool::~SequencedWorkerPool() {} 713 SequencedWorkerPool::~SequencedWorkerPool() {}
663 714
664 void SequencedWorkerPool::OnDestruct() const { 715 void SequencedWorkerPool::OnDestruct() const {
665 // TODO(akalin): Once we can easily check if we're on a worker 716 // TODO(akalin): Once we can easily check if we're on a worker
666 // thread or not, use that instead of restricting destruction to 717 // thread or not, use that instead of restricting destruction to
667 // only the constructor message loop. 718 // only the constructor message loop.
668 if (constructor_message_loop_->BelongsToCurrentThread()) { 719 if (constructor_message_loop_->BelongsToCurrentThread())
669 delete this; 720 delete this;
670 } else { 721 else
671 constructor_message_loop_->DeleteSoon(FROM_HERE, this); 722 constructor_message_loop_->DeleteSoon(FROM_HERE, this);
672 }
673 } 723 }
674 724
675 SequencedWorkerPool::SequenceToken SequencedWorkerPool::GetSequenceToken() { 725 SequencedWorkerPool::SequenceToken SequencedWorkerPool::GetSequenceToken() {
676 return inner_->GetSequenceToken(); 726 return inner_->GetSequenceToken();
677 } 727 }
678 728
679 SequencedWorkerPool::SequenceToken SequencedWorkerPool::GetNamedSequenceToken( 729 SequencedWorkerPool::SequenceToken SequencedWorkerPool::GetNamedSequenceToken(
680 const std::string& name) { 730 const std::string& name) {
681 return inner_->GetNamedSequenceToken(name); 731 return inner_->GetNamedSequenceToken(name);
682 } 732 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 } 791 }
742 792
743 bool SequencedWorkerPool::RunsTasksOnCurrentThread() const { 793 bool SequencedWorkerPool::RunsTasksOnCurrentThread() const {
744 return inner_->RunsTasksOnCurrentThread(); 794 return inner_->RunsTasksOnCurrentThread();
745 } 795 }
746 796
747 void SequencedWorkerPool::FlushForTesting() { 797 void SequencedWorkerPool::FlushForTesting() {
748 inner_->FlushForTesting(); 798 inner_->FlushForTesting();
749 } 799 }
750 800
801 void SequencedWorkerPool::TriggerSpuriousWorkSignalForTesting() {
802 inner_->TriggerSpuriousWorkSignalForTesting();
803 }
804
805 int SequencedWorkerPool::GetWorkSignalCountForTesting() const {
806 return inner_->GetWorkSignalCountForTesting();
807 }
808
751 void SequencedWorkerPool::Shutdown() { 809 void SequencedWorkerPool::Shutdown() {
810 DCHECK(constructor_message_loop_->BelongsToCurrentThread());
752 inner_->Shutdown(); 811 inner_->Shutdown();
753 } 812 }
754 813
755 void SequencedWorkerPool::SetTestingObserver(TestingObserver* observer) { 814 void SequencedWorkerPool::SetTestingObserver(TestingObserver* observer) {
756 inner_->SetTestingObserver(observer); 815 inner_->SetTestingObserver(observer);
757 } 816 }
758 817
759 } // namespace base 818 } // 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