OLD | NEW |
---|---|
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 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
382 // This lock protects |everything in this class|. Do not read or modify | 382 // This lock protects |everything in this class|. Do not read or modify |
383 // anything without holding this lock. Do not block while holding this | 383 // anything without holding this lock. Do not block while holding this |
384 // lock. | 384 // lock. |
385 mutable Lock lock_; | 385 mutable Lock lock_; |
386 | 386 |
387 // Condition variable that is waited on by worker threads until new | 387 // Condition variable that is waited on by worker threads until new |
388 // tasks are posted or shutdown starts. | 388 // tasks are posted or shutdown starts. |
389 ConditionVariable has_work_cv_; | 389 ConditionVariable has_work_cv_; |
390 | 390 |
391 // Condition variable that is waited on by non-worker threads (in | 391 // Condition variable that is waited on by non-worker threads (in |
392 // FlushForTesting()) until IsIdle() goes to true. | 392 // FlushForTesting()) until IsIdle() goes to true or Shutdown completes. |
393 ConditionVariable is_idle_cv_; | 393 ConditionVariable is_idle_cv_; |
394 | 394 |
395 // Condition variable that is waited on by non-worker threads (in | 395 // Condition variable that is waited on by non-worker threads (in |
396 // Shutdown()) until CanShutdown() goes to true. | 396 // Shutdown()) until CanShutdown() goes to true. |
397 ConditionVariable can_shutdown_cv_; | 397 ConditionVariable can_shutdown_cv_; |
398 | 398 |
399 // The maximum number of worker threads we'll create. | 399 // The maximum number of worker threads we'll create. |
400 const size_t max_threads_; | 400 const size_t max_threads_; |
401 | 401 |
402 const std::string thread_name_prefix_; | 402 const std::string thread_name_prefix_; |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
603 bool SequencedWorkerPool::Inner::IsRunningSequenceOnCurrentThread( | 603 bool SequencedWorkerPool::Inner::IsRunningSequenceOnCurrentThread( |
604 SequenceToken sequence_token) const { | 604 SequenceToken sequence_token) const { |
605 AutoLock lock(lock_); | 605 AutoLock lock(lock_); |
606 ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId()); | 606 ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId()); |
607 if (found == threads_.end()) | 607 if (found == threads_.end()) |
608 return false; | 608 return false; |
609 return found->second->running_sequence().Equals(sequence_token); | 609 return found->second->running_sequence().Equals(sequence_token); |
610 } | 610 } |
611 | 611 |
612 void SequencedWorkerPool::Inner::FlushForTesting() { | 612 void SequencedWorkerPool::Inner::FlushForTesting() { |
613 base::ThreadRestrictions::ScopedAllowWait allow_wait; | |
613 AutoLock lock(lock_); | 614 AutoLock lock(lock_); |
614 while (!IsIdle()) | 615 while (!IsIdle() && !shutdown_called_) |
615 is_idle_cv_.Wait(); | 616 is_idle_cv_.Wait(); |
616 } | 617 } |
617 | 618 |
618 void SequencedWorkerPool::Inner::SignalHasWorkForTesting() { | 619 void SequencedWorkerPool::Inner::SignalHasWorkForTesting() { |
619 SignalHasWork(); | 620 SignalHasWork(); |
620 } | 621 } |
621 | 622 |
622 void SequencedWorkerPool::Inner::Shutdown( | 623 void SequencedWorkerPool::Inner::Shutdown( |
623 int max_new_blocking_tasks_after_shutdown) { | 624 int max_new_blocking_tasks_after_shutdown) { |
624 DCHECK_GE(max_new_blocking_tasks_after_shutdown, 0); | 625 DCHECK_GE(max_new_blocking_tasks_after_shutdown, 0); |
625 { | 626 { |
626 AutoLock lock(lock_); | 627 AutoLock lock(lock_); |
627 | 628 |
628 if (shutdown_called_) | 629 if (shutdown_called_) |
629 return; | 630 return; |
630 shutdown_called_ = true; | 631 shutdown_called_ = true; |
michaeln
2012/12/21 23:43:19
Hi Fred,
Not sure if you've been following along
| |
631 max_blocking_tasks_after_shutdown_ = max_new_blocking_tasks_after_shutdown; | 632 max_blocking_tasks_after_shutdown_ = max_new_blocking_tasks_after_shutdown; |
632 | 633 |
633 // Tickle the threads. This will wake up a waiting one so it will know that | 634 // Tickle the threads. This will wake up a waiting one so it will know that |
634 // it can exit, which in turn will wake up any other waiting ones. | 635 // it can exit, which in turn will wake up any other waiting ones. |
635 SignalHasWork(); | 636 SignalHasWork(); |
636 | 637 |
637 // There are no pending or running tasks blocking shutdown, we're done. | 638 // There are no pending or running tasks blocking shutdown, we're done. |
638 if (CanShutdown()) | 639 if (CanShutdown()) { |
640 is_idle_cv_.Signal(); | |
639 return; | 641 return; |
642 } | |
640 } | 643 } |
641 | 644 |
642 // If we're here, then something is blocking shutdown. So wait for | 645 // If we're here, then something is blocking shutdown. So wait for |
643 // CanShutdown() to go to true. | 646 // CanShutdown() to go to true. |
644 | 647 |
645 if (testing_observer_) | 648 if (testing_observer_) |
646 testing_observer_->WillWaitForShutdown(); | 649 testing_observer_->WillWaitForShutdown(); |
647 | 650 |
648 TimeTicks shutdown_wait_begin = TimeTicks::Now(); | 651 TimeTicks shutdown_wait_begin = TimeTicks::Now(); |
649 | 652 |
650 { | 653 { |
651 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 654 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
652 AutoLock lock(lock_); | 655 AutoLock lock(lock_); |
653 while (!CanShutdown()) | 656 while (!CanShutdown()) |
654 can_shutdown_cv_.Wait(); | 657 can_shutdown_cv_.Wait(); |
658 is_idle_cv_.Signal(); | |
655 } | 659 } |
656 UMA_HISTOGRAM_TIMES("SequencedWorkerPool.ShutdownDelayTime", | 660 UMA_HISTOGRAM_TIMES("SequencedWorkerPool.ShutdownDelayTime", |
657 TimeTicks::Now() - shutdown_wait_begin); | 661 TimeTicks::Now() - shutdown_wait_begin); |
658 } | 662 } |
659 | 663 |
660 void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) { | 664 void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) { |
661 { | 665 { |
662 AutoLock lock(lock_); | 666 AutoLock lock(lock_); |
663 DCHECK(thread_being_created_); | 667 DCHECK(thread_being_created_); |
664 thread_being_created_ = false; | 668 thread_being_created_ = false; |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1152 void SequencedWorkerPool::SignalHasWorkForTesting() { | 1156 void SequencedWorkerPool::SignalHasWorkForTesting() { |
1153 inner_->SignalHasWorkForTesting(); | 1157 inner_->SignalHasWorkForTesting(); |
1154 } | 1158 } |
1155 | 1159 |
1156 void SequencedWorkerPool::Shutdown(int max_new_blocking_tasks_after_shutdown) { | 1160 void SequencedWorkerPool::Shutdown(int max_new_blocking_tasks_after_shutdown) { |
1157 DCHECK(constructor_message_loop_->BelongsToCurrentThread()); | 1161 DCHECK(constructor_message_loop_->BelongsToCurrentThread()); |
1158 inner_->Shutdown(max_new_blocking_tasks_after_shutdown); | 1162 inner_->Shutdown(max_new_blocking_tasks_after_shutdown); |
1159 } | 1163 } |
1160 | 1164 |
1161 } // namespace base | 1165 } // namespace base |
OLD | NEW |