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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
274 SequenceToken sequence_token, | 274 SequenceToken sequence_token, |
275 WorkerShutdown shutdown_behavior, | 275 WorkerShutdown shutdown_behavior, |
276 const tracked_objects::Location& from_here, | 276 const tracked_objects::Location& from_here, |
277 const Closure& task, | 277 const Closure& task, |
278 TimeDelta delay); | 278 TimeDelta delay); |
279 | 279 |
280 bool RunsTasksOnCurrentThread() const; | 280 bool RunsTasksOnCurrentThread() const; |
281 | 281 |
282 bool IsRunningSequenceOnCurrentThread(SequenceToken sequence_token) const; | 282 bool IsRunningSequenceOnCurrentThread(SequenceToken sequence_token) const; |
283 | 283 |
284 void FlushForTesting(); | 284 void CleanupForTesting(); |
285 | 285 |
286 void SignalHasWorkForTesting(); | 286 void SignalHasWorkForTesting(); |
287 | 287 |
288 int GetWorkSignalCountForTesting() const; | 288 int GetWorkSignalCountForTesting() const; |
289 | 289 |
290 void Shutdown(int max_blocking_tasks_after_shutdown); | 290 void Shutdown(int max_blocking_tasks_after_shutdown); |
291 | 291 |
292 // Runs the worker loop on the background thread. | 292 // Runs the worker loop on the background thread. |
293 void ThreadLoop(Worker* this_worker); | 293 void ThreadLoop(Worker* this_worker); |
294 | 294 |
295 private: | 295 private: |
296 enum GetWorkStatus { | 296 enum GetWorkStatus { |
297 GET_WORK_FOUND, | 297 GET_WORK_FOUND, |
298 GET_WORK_NOT_FOUND, | 298 GET_WORK_NOT_FOUND, |
299 GET_WORK_WAIT, | 299 GET_WORK_WAIT, |
300 }; | 300 }; |
301 | 301 |
302 // Returns whether there are no more pending tasks and all threads | 302 enum CleanupState { |
303 // are idle. Must be called under lock. | 303 CLEANUP_REQUESTED, |
304 bool IsIdle() const; | 304 CLEANUP_WAITING, |
305 CLEANUP_RUNNING, | |
306 CLEANUP_DONE | |
307 }; | |
305 | 308 |
306 // Called from within the lock, this converts the given token name into a | 309 // Called from within the lock, this converts the given token name into a |
307 // token ID, creating a new one if necessary. | 310 // token ID, creating a new one if necessary. |
308 int LockedGetNamedTokenID(const std::string& name); | 311 int LockedGetNamedTokenID(const std::string& name); |
309 | 312 |
310 // Called from within the lock, this returns the next sequence task number. | 313 // Called from within the lock, this returns the next sequence task number. |
311 int64 LockedGetNextSequenceTaskNumber(); | 314 int64 LockedGetNextSequenceTaskNumber(); |
312 | 315 |
313 // Called from within the lock, returns the shutdown behavior of the task | 316 // Called from within the lock, returns the shutdown behavior of the task |
314 // running on the currently executing worker thread. If invoked from a thread | 317 // running on the currently executing worker thread. If invoked from a thread |
(...skipping 12 matching lines...) Expand all Loading... | |
327 // filled in the time to wait until the next task to run. In this case, the | 330 // filled in the time to wait until the next task to run. In this case, the |
328 // caller should wait the time. | 331 // caller should wait the time. |
329 // | 332 // |
330 // In any case, the calling code should clear the given | 333 // In any case, the calling code should clear the given |
331 // delete_these_outside_lock vector the next time the lock is released. | 334 // delete_these_outside_lock vector the next time the lock is released. |
332 // See the implementation for a more detailed description. | 335 // See the implementation for a more detailed description. |
333 GetWorkStatus GetWork(SequencedTask* task, | 336 GetWorkStatus GetWork(SequencedTask* task, |
334 TimeDelta* wait_time, | 337 TimeDelta* wait_time, |
335 std::vector<Closure>* delete_these_outside_lock); | 338 std::vector<Closure>* delete_these_outside_lock); |
336 | 339 |
340 void HandleCleanup(); | |
341 | |
337 // Peforms init and cleanup around running the given task. WillRun... | 342 // Peforms init and cleanup around running the given task. WillRun... |
338 // returns the value from PrepareToStartAdditionalThreadIfNecessary. | 343 // returns the value from PrepareToStartAdditionalThreadIfNecessary. |
339 // The calling code should call FinishStartingAdditionalThread once the | 344 // The calling code should call FinishStartingAdditionalThread once the |
340 // lock is released if the return values is nonzero. | 345 // lock is released if the return values is nonzero. |
341 int WillRunWorkerTask(const SequencedTask& task); | 346 int WillRunWorkerTask(const SequencedTask& task); |
342 void DidRunWorkerTask(const SequencedTask& task); | 347 void DidRunWorkerTask(const SequencedTask& task); |
343 | 348 |
344 // Returns true if there are no threads currently running the given | 349 // Returns true if there are no threads currently running the given |
345 // sequence token. | 350 // sequence token. |
346 bool IsSequenceTokenRunnable(int sequence_token_id) const; | 351 bool IsSequenceTokenRunnable(int sequence_token_id) const; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
382 // This lock protects |everything in this class|. Do not read or modify | 387 // This lock protects |everything in this class|. Do not read or modify |
383 // anything without holding this lock. Do not block while holding this | 388 // anything without holding this lock. Do not block while holding this |
384 // lock. | 389 // lock. |
385 mutable Lock lock_; | 390 mutable Lock lock_; |
386 | 391 |
387 // Condition variable that is waited on by worker threads until new | 392 // Condition variable that is waited on by worker threads until new |
388 // tasks are posted or shutdown starts. | 393 // tasks are posted or shutdown starts. |
389 ConditionVariable has_work_cv_; | 394 ConditionVariable has_work_cv_; |
390 | 395 |
391 // Condition variable that is waited on by non-worker threads (in | 396 // Condition variable that is waited on by non-worker threads (in |
392 // FlushForTesting()) until IsIdle() goes to true. | |
393 ConditionVariable is_idle_cv_; | |
394 | |
395 // Condition variable that is waited on by non-worker threads (in | |
396 // Shutdown()) until CanShutdown() goes to true. | 397 // Shutdown()) until CanShutdown() goes to true. |
397 ConditionVariable can_shutdown_cv_; | 398 ConditionVariable can_shutdown_cv_; |
398 | 399 |
399 // The maximum number of worker threads we'll create. | 400 // The maximum number of worker threads we'll create. |
400 const size_t max_threads_; | 401 const size_t max_threads_; |
401 | 402 |
402 const std::string thread_name_prefix_; | 403 const std::string thread_name_prefix_; |
403 | 404 |
404 // Associates all known sequence token names with their IDs. | 405 // Associates all known sequence token names with their IDs. |
405 std::map<std::string, int> named_sequence_tokens_; | 406 std::map<std::string, int> named_sequence_tokens_; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
443 int trace_id_; | 444 int trace_id_; |
444 | 445 |
445 // Set when Shutdown is called and no further tasks should be | 446 // Set when Shutdown is called and no further tasks should be |
446 // allowed, though we may still be running existing tasks. | 447 // allowed, though we may still be running existing tasks. |
447 bool shutdown_called_; | 448 bool shutdown_called_; |
448 | 449 |
449 // The number of new BLOCK_SHUTDOWN tasks that may be posted after Shudown() | 450 // The number of new BLOCK_SHUTDOWN tasks that may be posted after Shudown() |
450 // has been called. | 451 // has been called. |
451 int max_blocking_tasks_after_shutdown_; | 452 int max_blocking_tasks_after_shutdown_; |
452 | 453 |
454 // State used to cleanup for testing, all guarded by lock_. | |
455 CleanupState cleanup_state_; | |
456 size_t cleanup_idlers_; | |
457 ConditionVariable cleanup_cv_; | |
458 | |
453 TestingObserver* const testing_observer_; | 459 TestingObserver* const testing_observer_; |
454 | 460 |
455 DISALLOW_COPY_AND_ASSIGN(Inner); | 461 DISALLOW_COPY_AND_ASSIGN(Inner); |
456 }; | 462 }; |
457 | 463 |
458 // Worker definitions --------------------------------------------------------- | 464 // Worker definitions --------------------------------------------------------- |
459 | 465 |
460 SequencedWorkerPool::Worker::Worker( | 466 SequencedWorkerPool::Worker::Worker( |
461 const scoped_refptr<SequencedWorkerPool>& worker_pool, | 467 const scoped_refptr<SequencedWorkerPool>& worker_pool, |
462 int thread_number, | 468 int thread_number, |
(...skipping 23 matching lines...) Expand all Loading... | |
486 | 492 |
487 SequencedWorkerPool::Inner::Inner( | 493 SequencedWorkerPool::Inner::Inner( |
488 SequencedWorkerPool* worker_pool, | 494 SequencedWorkerPool* worker_pool, |
489 size_t max_threads, | 495 size_t max_threads, |
490 const std::string& thread_name_prefix, | 496 const std::string& thread_name_prefix, |
491 TestingObserver* observer) | 497 TestingObserver* observer) |
492 : worker_pool_(worker_pool), | 498 : worker_pool_(worker_pool), |
493 last_sequence_number_(0), | 499 last_sequence_number_(0), |
494 lock_(), | 500 lock_(), |
495 has_work_cv_(&lock_), | 501 has_work_cv_(&lock_), |
496 is_idle_cv_(&lock_), | |
497 can_shutdown_cv_(&lock_), | 502 can_shutdown_cv_(&lock_), |
498 max_threads_(max_threads), | 503 max_threads_(max_threads), |
499 thread_name_prefix_(thread_name_prefix), | 504 thread_name_prefix_(thread_name_prefix), |
500 thread_being_created_(false), | 505 thread_being_created_(false), |
501 waiting_thread_count_(0), | 506 waiting_thread_count_(0), |
502 blocking_shutdown_thread_count_(0), | 507 blocking_shutdown_thread_count_(0), |
503 next_sequence_task_number_(0), | 508 next_sequence_task_number_(0), |
504 blocking_shutdown_pending_task_count_(0), | 509 blocking_shutdown_pending_task_count_(0), |
505 trace_id_(0), | 510 trace_id_(0), |
506 shutdown_called_(false), | 511 shutdown_called_(false), |
507 max_blocking_tasks_after_shutdown_(0), | 512 max_blocking_tasks_after_shutdown_(0), |
513 cleanup_state_(CLEANUP_DONE), | |
514 cleanup_idlers_(0), | |
515 cleanup_cv_(&lock_), | |
508 testing_observer_(observer) {} | 516 testing_observer_(observer) {} |
509 | 517 |
510 SequencedWorkerPool::Inner::~Inner() { | 518 SequencedWorkerPool::Inner::~Inner() { |
511 // You must call Shutdown() before destroying the pool. | 519 // You must call Shutdown() before destroying the pool. |
512 DCHECK(shutdown_called_); | 520 DCHECK(shutdown_called_); |
513 | 521 |
514 // Need to explicitly join with the threads before they're destroyed or else | 522 // Need to explicitly join with the threads before they're destroyed or else |
515 // they will be running when our object is half torn down. | 523 // they will be running when our object is half torn down. |
516 for (ThreadMap::iterator it = threads_.begin(); it != threads_.end(); ++it) | 524 for (ThreadMap::iterator it = threads_.begin(); it != threads_.end(); ++it) |
517 it->second->Join(); | 525 it->second->Join(); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
602 | 610 |
603 bool SequencedWorkerPool::Inner::IsRunningSequenceOnCurrentThread( | 611 bool SequencedWorkerPool::Inner::IsRunningSequenceOnCurrentThread( |
604 SequenceToken sequence_token) const { | 612 SequenceToken sequence_token) const { |
605 AutoLock lock(lock_); | 613 AutoLock lock(lock_); |
606 ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId()); | 614 ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId()); |
607 if (found == threads_.end()) | 615 if (found == threads_.end()) |
608 return false; | 616 return false; |
609 return found->second->running_sequence().Equals(sequence_token); | 617 return found->second->running_sequence().Equals(sequence_token); |
610 } | 618 } |
611 | 619 |
612 void SequencedWorkerPool::Inner::FlushForTesting() { | 620 // See https://code.google.com/p/chromium/issues/detail?id=168415 |
621 // * executes all pending non-delayed tasks and deletes the associated closures | |
622 // * skips executing all pending delayed tasks, but does delete their closures | |
623 // * accepts new tasks while in the act of cleaning up | |
624 void SequencedWorkerPool::Inner::CleanupForTesting() { | |
625 DCHECK(!RunsTasksOnCurrentThread()); | |
626 base::ThreadRestrictions::ScopedAllowWait allow_wait; | |
613 AutoLock lock(lock_); | 627 AutoLock lock(lock_); |
614 while (!IsIdle()) | 628 if (shutdown_called_) |
615 is_idle_cv_.Wait(); | 629 return; |
630 CHECK_EQ(CLEANUP_DONE, cleanup_state_); | |
631 if (!thread_being_created_ && threads_.empty()) | |
632 return; | |
633 cleanup_state_ = CLEANUP_REQUESTED; | |
634 cleanup_idlers_ = 0; | |
635 has_work_cv_.Signal(); | |
636 while (cleanup_state_ != CLEANUP_DONE) | |
637 cleanup_cv_.Wait(); | |
616 } | 638 } |
617 | 639 |
618 void SequencedWorkerPool::Inner::SignalHasWorkForTesting() { | 640 void SequencedWorkerPool::Inner::SignalHasWorkForTesting() { |
619 SignalHasWork(); | 641 SignalHasWork(); |
620 } | 642 } |
621 | 643 |
622 void SequencedWorkerPool::Inner::Shutdown( | 644 void SequencedWorkerPool::Inner::Shutdown( |
623 int max_new_blocking_tasks_after_shutdown) { | 645 int max_new_blocking_tasks_after_shutdown) { |
624 DCHECK_GE(max_new_blocking_tasks_after_shutdown, 0); | 646 DCHECK_GE(max_new_blocking_tasks_after_shutdown, 0); |
625 { | 647 { |
626 AutoLock lock(lock_); | 648 AutoLock lock(lock_); |
627 | |
628 if (shutdown_called_) | 649 if (shutdown_called_) |
629 return; | 650 return; |
651 CHECK_EQ(CLEANUP_DONE, cleanup_state_); | |
630 shutdown_called_ = true; | 652 shutdown_called_ = true; |
631 max_blocking_tasks_after_shutdown_ = max_new_blocking_tasks_after_shutdown; | 653 max_blocking_tasks_after_shutdown_ = max_new_blocking_tasks_after_shutdown; |
632 | 654 |
633 // Tickle the threads. This will wake up a waiting one so it will know that | 655 // 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. | 656 // it can exit, which in turn will wake up any other waiting ones. |
635 SignalHasWork(); | 657 SignalHasWork(); |
636 | 658 |
637 // There are no pending or running tasks blocking shutdown, we're done. | 659 // There are no pending or running tasks blocking shutdown, we're done. |
638 if (CanShutdown()) | 660 if (CanShutdown()) |
639 return; | 661 return; |
(...skipping 25 matching lines...) Expand all Loading... | |
665 std::pair<ThreadMap::iterator, bool> result = | 687 std::pair<ThreadMap::iterator, bool> result = |
666 threads_.insert( | 688 threads_.insert( |
667 std::make_pair(this_worker->tid(), make_linked_ptr(this_worker))); | 689 std::make_pair(this_worker->tid(), make_linked_ptr(this_worker))); |
668 DCHECK(result.second); | 690 DCHECK(result.second); |
669 | 691 |
670 while (true) { | 692 while (true) { |
671 #if defined(OS_MACOSX) | 693 #if defined(OS_MACOSX) |
672 base::mac::ScopedNSAutoreleasePool autorelease_pool; | 694 base::mac::ScopedNSAutoreleasePool autorelease_pool; |
673 #endif | 695 #endif |
674 | 696 |
697 if (cleanup_state_ != CLEANUP_DONE) | |
698 HandleCleanup(); | |
jar (doing other things)
2013/01/15 22:59:59
It is surprising we call this in 3 of the 4 states
| |
699 | |
675 // See GetWork for what delete_these_outside_lock is doing. | 700 // See GetWork for what delete_these_outside_lock is doing. |
676 SequencedTask task; | 701 SequencedTask task; |
677 TimeDelta wait_time; | 702 TimeDelta wait_time; |
678 std::vector<Closure> delete_these_outside_lock; | 703 std::vector<Closure> delete_these_outside_lock; |
679 GetWorkStatus status = | 704 GetWorkStatus status = |
680 GetWork(&task, &wait_time, &delete_these_outside_lock); | 705 GetWork(&task, &wait_time, &delete_these_outside_lock); |
681 if (status == GET_WORK_FOUND) { | 706 if (status == GET_WORK_FOUND) { |
682 TRACE_EVENT_FLOW_END0("task", "SequencedWorkerPool::PostTask", | 707 TRACE_EVENT_FLOW_END0("task", "SequencedWorkerPool::PostTask", |
683 TRACE_ID_MANGLE(GetTaskTraceID(task, static_cast<void*>(this)))); | 708 TRACE_ID_MANGLE(GetTaskTraceID(task, static_cast<void*>(this)))); |
684 TRACE_EVENT2("task", "SequencedWorkerPool::ThreadLoop", | 709 TRACE_EVENT2("task", "SequencedWorkerPool::ThreadLoop", |
(...skipping 25 matching lines...) Expand all Loading... | |
710 start_time, tracked_objects::ThreadData::NowForEndOfRun()); | 735 start_time, tracked_objects::ThreadData::NowForEndOfRun()); |
711 | 736 |
712 this_worker->set_running_task_info( | 737 this_worker->set_running_task_info( |
713 SequenceToken(), CONTINUE_ON_SHUTDOWN); | 738 SequenceToken(), CONTINUE_ON_SHUTDOWN); |
714 | 739 |
715 // Make sure our task is erased outside the lock for the same reason | 740 // Make sure our task is erased outside the lock for the same reason |
716 // we do this with delete_these_oustide_lock. | 741 // we do this with delete_these_oustide_lock. |
717 task.task = Closure(); | 742 task.task = Closure(); |
718 } | 743 } |
719 DidRunWorkerTask(task); // Must be done inside the lock. | 744 DidRunWorkerTask(task); // Must be done inside the lock. |
745 } else if (cleanup_state_ == CLEANUP_RUNNING) { | |
746 switch (status) { | |
747 case GET_WORK_NOT_FOUND: | |
748 cleanup_state_ = CLEANUP_DONE; | |
749 cleanup_cv_.Broadcast(); | |
750 break; | |
751 case GET_WORK_WAIT: { | |
752 AutoUnlock unlock(lock_); | |
753 delete_these_outside_lock.clear(); | |
754 } | |
755 break; | |
756 default: | |
757 NOTREACHED(); | |
758 } | |
720 } else { | 759 } else { |
721 // When we're terminating and there's no more work, we can | 760 // When we're terminating and there's no more work, we can |
722 // shut down, other workers can complete any pending or new tasks. | 761 // shut down, other workers can complete any pending or new tasks. |
723 // We can get additional tasks posted after shutdown_called_ is set | 762 // We can get additional tasks posted after shutdown_called_ is set |
724 // but only worker threads are allowed to post tasks at that time, and | 763 // but only worker threads are allowed to post tasks at that time, and |
725 // the workers responsible for posting those tasks will be available | 764 // the workers responsible for posting those tasks will be available |
726 // to run them. Also, there may be some tasks stuck behind running | 765 // to run them. Also, there may be some tasks stuck behind running |
727 // ones with the same sequence token, but additional threads won't | 766 // ones with the same sequence token, but additional threads won't |
728 // help this case. | 767 // help this case. |
729 if (shutdown_called_ && | 768 if (shutdown_called_ && |
730 blocking_shutdown_pending_task_count_ == 0) | 769 blocking_shutdown_pending_task_count_ == 0) |
731 break; | 770 break; |
732 waiting_thread_count_++; | 771 waiting_thread_count_++; |
733 // This is the only time that IsIdle() can go to true. | |
734 if (IsIdle()) | |
735 is_idle_cv_.Signal(); | |
736 | 772 |
737 switch (status) { | 773 switch (status) { |
738 case GET_WORK_NOT_FOUND: | 774 case GET_WORK_NOT_FOUND: |
739 has_work_cv_.Wait(); | 775 has_work_cv_.Wait(); |
740 break; | 776 break; |
741 case GET_WORK_WAIT: | 777 case GET_WORK_WAIT: |
742 has_work_cv_.TimedWait(wait_time); | 778 has_work_cv_.TimedWait(wait_time); |
743 break; | 779 break; |
744 default: | 780 default: |
745 NOTREACHED(); | 781 NOTREACHED(); |
746 } | 782 } |
747 waiting_thread_count_--; | 783 waiting_thread_count_--; |
748 } | 784 } |
749 } | 785 } |
750 } // Release lock_. | 786 } // Release lock_. |
751 | 787 |
752 // We noticed we should exit. Wake up the next worker so it knows it should | 788 // We noticed we should exit. Wake up the next worker so it knows it should |
753 // exit as well (because the Shutdown() code only signals once). | 789 // exit as well (because the Shutdown() code only signals once). |
754 SignalHasWork(); | 790 SignalHasWork(); |
755 | 791 |
756 // Possibly unblock shutdown. | 792 // Possibly unblock shutdown. |
757 can_shutdown_cv_.Signal(); | 793 can_shutdown_cv_.Signal(); |
758 } | 794 } |
759 | 795 |
760 bool SequencedWorkerPool::Inner::IsIdle() const { | 796 void SequencedWorkerPool::Inner::HandleCleanup() { |
761 lock_.AssertAcquired(); | 797 lock_.AssertAcquired(); |
762 return pending_tasks_.empty() && waiting_thread_count_ == threads_.size(); | 798 if (cleanup_state_ == CLEANUP_REQUESTED) { |
799 // We win! We get to do the cleanup as soon as the others wise up and idle. | |
800 cleanup_state_ = CLEANUP_WAITING; | |
801 while (thread_being_created_ && | |
802 cleanup_idlers_ != threads_.size() - 1) { | |
803 has_work_cv_.Signal(); | |
804 cleanup_cv_.Wait(); | |
805 } | |
806 cleanup_state_ = CLEANUP_RUNNING; | |
807 return; | |
808 } | |
809 if (cleanup_state_ == CLEANUP_WAITING) { | |
810 // Another worker thread is cleaning up, we idle here until thats done. | |
811 ++cleanup_idlers_; | |
812 cleanup_cv_.Broadcast(); | |
813 while (cleanup_state_ != CLEANUP_DONE) | |
814 cleanup_cv_.Wait(); | |
815 return; | |
816 } | |
817 DCHECK_EQ(CLEANUP_RUNNING, cleanup_state_); | |
763 } | 818 } |
764 | 819 |
765 int SequencedWorkerPool::Inner::LockedGetNamedTokenID( | 820 int SequencedWorkerPool::Inner::LockedGetNamedTokenID( |
766 const std::string& name) { | 821 const std::string& name) { |
767 lock_.AssertAcquired(); | 822 lock_.AssertAcquired(); |
768 DCHECK(!name.empty()); | 823 DCHECK(!name.empty()); |
769 | 824 |
770 std::map<std::string, int>::const_iterator found = | 825 std::map<std::string, int>::const_iterator found = |
771 named_sequence_tokens_.find(name); | 826 named_sequence_tokens_.find(name); |
772 if (found != named_sequence_tokens_.end()) | 827 if (found != named_sequence_tokens_.end()) |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
831 // We assume that the loop below doesn't take too long and so we can just do | 886 // We assume that the loop below doesn't take too long and so we can just do |
832 // a single call to TimeTicks::Now(). | 887 // a single call to TimeTicks::Now(). |
833 const TimeTicks current_time = TimeTicks::Now(); | 888 const TimeTicks current_time = TimeTicks::Now(); |
834 while (i != pending_tasks_.end()) { | 889 while (i != pending_tasks_.end()) { |
835 if (!IsSequenceTokenRunnable(i->sequence_token_id)) { | 890 if (!IsSequenceTokenRunnable(i->sequence_token_id)) { |
836 unrunnable_tasks++; | 891 unrunnable_tasks++; |
837 ++i; | 892 ++i; |
838 continue; | 893 continue; |
839 } | 894 } |
840 | 895 |
896 // Let's try running all delayed tasks during cleanup? | |
jar (doing other things)
2013/01/15 22:59:59
What's up with the question mark?
...also... I th
| |
897 if (cleanup_state_ == CLEANUP_RUNNING) { | |
898 *task = *i; | |
899 pending_tasks_.erase(i); | |
900 if (task->shutdown_behavior == BLOCK_SHUTDOWN) | |
901 blocking_shutdown_pending_task_count_--; | |
902 status = GET_WORK_FOUND; | |
903 break; | |
904 } | |
905 | |
841 if (i->time_to_run > current_time) { | 906 if (i->time_to_run > current_time) { |
842 // The time to run has not come yet. | 907 // The time to run has not come yet. |
843 *wait_time = i->time_to_run - current_time; | 908 *wait_time = i->time_to_run - current_time; |
844 status = GET_WORK_WAIT; | 909 status = GET_WORK_WAIT; |
910 /* | |
911 if (cleanup_state_ == CLEANUP_RUNNING) { | |
912 delete_these_outside_lock->push_back(i->task); | |
913 pending_tasks_.erase(i); | |
914 } | |
915 */ | |
845 break; | 916 break; |
846 } | 917 } |
847 | 918 |
848 if (shutdown_called_ && i->shutdown_behavior != BLOCK_SHUTDOWN) { | 919 if (shutdown_called_ && i->shutdown_behavior != BLOCK_SHUTDOWN) { |
849 // We're shutting down and the task we just found isn't blocking | 920 // We're shutting down and the task we just found isn't blocking |
850 // shutdown. Delete it and get more work. | 921 // shutdown. Delete it and get more work. |
851 // | 922 // |
852 // Note that we do not want to delete unrunnable tasks. Deleting a task | 923 // Note that we do not want to delete unrunnable tasks. Deleting a task |
853 // can have side effects (like freeing some objects) and deleting a | 924 // can have side effects (like freeing some objects) and deleting a |
854 // task that's supposed to run after one that's currently running could | 925 // task that's supposed to run after one that's currently running could |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1139 bool SequencedWorkerPool::RunsTasksOnCurrentThread() const { | 1210 bool SequencedWorkerPool::RunsTasksOnCurrentThread() const { |
1140 return inner_->RunsTasksOnCurrentThread(); | 1211 return inner_->RunsTasksOnCurrentThread(); |
1141 } | 1212 } |
1142 | 1213 |
1143 bool SequencedWorkerPool::IsRunningSequenceOnCurrentThread( | 1214 bool SequencedWorkerPool::IsRunningSequenceOnCurrentThread( |
1144 SequenceToken sequence_token) const { | 1215 SequenceToken sequence_token) const { |
1145 return inner_->IsRunningSequenceOnCurrentThread(sequence_token); | 1216 return inner_->IsRunningSequenceOnCurrentThread(sequence_token); |
1146 } | 1217 } |
1147 | 1218 |
1148 void SequencedWorkerPool::FlushForTesting() { | 1219 void SequencedWorkerPool::FlushForTesting() { |
1149 inner_->FlushForTesting(); | 1220 inner_->CleanupForTesting(); |
1150 } | 1221 } |
1151 | 1222 |
1152 void SequencedWorkerPool::SignalHasWorkForTesting() { | 1223 void SequencedWorkerPool::SignalHasWorkForTesting() { |
1153 inner_->SignalHasWorkForTesting(); | 1224 inner_->SignalHasWorkForTesting(); |
1154 } | 1225 } |
1155 | 1226 |
1156 void SequencedWorkerPool::Shutdown(int max_new_blocking_tasks_after_shutdown) { | 1227 void SequencedWorkerPool::Shutdown(int max_new_blocking_tasks_after_shutdown) { |
1157 DCHECK(constructor_message_loop_->BelongsToCurrentThread()); | 1228 DCHECK(constructor_message_loop_->BelongsToCurrentThread()); |
1158 inner_->Shutdown(max_new_blocking_tasks_after_shutdown); | 1229 inner_->Shutdown(max_new_blocking_tasks_after_shutdown); |
1159 } | 1230 } |
1160 | 1231 |
1161 } // namespace base | 1232 } // namespace base |
OLD | NEW |