| 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 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 ThreadMap threads_; | 365 ThreadMap threads_; |
| 366 | 366 |
| 367 // Set to true when we're in the process of creating another thread. | 367 // Set to true when we're in the process of creating another thread. |
| 368 // See PrepareToStartAdditionalThreadIfHelpful for more. | 368 // See PrepareToStartAdditionalThreadIfHelpful for more. |
| 369 bool thread_being_created_; | 369 bool thread_being_created_; |
| 370 | 370 |
| 371 // Number of threads currently waiting for work. | 371 // Number of threads currently waiting for work. |
| 372 size_t waiting_thread_count_; | 372 size_t waiting_thread_count_; |
| 373 | 373 |
| 374 // Number of threads currently running tasks that have the BLOCK_SHUTDOWN | 374 // Number of threads currently running tasks that have the BLOCK_SHUTDOWN |
| 375 // flag set. | 375 // or SKIP_ON_SHUTDOWN flag set. |
| 376 size_t blocking_shutdown_thread_count_; | 376 size_t blocking_shutdown_thread_count_; |
| 377 | 377 |
| 378 // In-order list of all pending tasks. These are tasks waiting for a thread | 378 // In-order list of all pending tasks. These are tasks waiting for a thread |
| 379 // to run on or that are blocked on a previous task in their sequence. | 379 // to run on or that are blocked on a previous task in their sequence. |
| 380 // | 380 // |
| 381 // We maintain the pending_task_count_ separately for metrics because | 381 // We maintain the pending_task_count_ separately for metrics because |
| 382 // list.size() can be linear time. | 382 // list.size() can be linear time. |
| 383 std::list<SequencedTask> pending_tasks_; | 383 std::list<SequencedTask> pending_tasks_; |
| 384 size_t pending_task_count_; | 384 size_t pending_task_count_; |
| 385 | 385 |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 752 return found_task; | 752 return found_task; |
| 753 } | 753 } |
| 754 | 754 |
| 755 int SequencedWorkerPool::Inner::WillRunWorkerTask(const SequencedTask& task) { | 755 int SequencedWorkerPool::Inner::WillRunWorkerTask(const SequencedTask& task) { |
| 756 lock_.AssertAcquired(); | 756 lock_.AssertAcquired(); |
| 757 | 757 |
| 758 // Mark the task's sequence number as in use. | 758 // Mark the task's sequence number as in use. |
| 759 if (task.sequence_token_id) | 759 if (task.sequence_token_id) |
| 760 current_sequences_.insert(task.sequence_token_id); | 760 current_sequences_.insert(task.sequence_token_id); |
| 761 | 761 |
| 762 if (task.shutdown_behavior == BLOCK_SHUTDOWN) | 762 // Ensure that threads running tasks posted with either SKIP_ON_SHUTDOWN |
| 763 // or BLOCK_SHUTDOWN will prevent shutdown until that task or thread |
| 764 // completes. |
| 765 if (task.shutdown_behavior != CONTINUE_ON_SHUTDOWN) |
| 763 blocking_shutdown_thread_count_++; | 766 blocking_shutdown_thread_count_++; |
| 764 | 767 |
| 765 // We just picked up a task. Since StartAdditionalThreadIfHelpful only | 768 // We just picked up a task. Since StartAdditionalThreadIfHelpful only |
| 766 // creates a new thread if there is no free one, there is a race when posting | 769 // creates a new thread if there is no free one, there is a race when posting |
| 767 // tasks that many tasks could have been posted before a thread started | 770 // tasks that many tasks could have been posted before a thread started |
| 768 // running them, so only one thread would have been created. So we also check | 771 // running them, so only one thread would have been created. So we also check |
| 769 // whether we should create more threads after removing our task from the | 772 // whether we should create more threads after removing our task from the |
| 770 // queue, which also has the nice side effect of creating the workers from | 773 // queue, which also has the nice side effect of creating the workers from |
| 771 // background threads rather than the main thread of the app. | 774 // background threads rather than the main thread of the app. |
| 772 // | 775 // |
| 773 // If another thread wasn't created, we want to wake up an existing thread | 776 // If another thread wasn't created, we want to wake up an existing thread |
| 774 // if there is one waiting to pick up the next task. | 777 // if there is one waiting to pick up the next task. |
| 775 // | 778 // |
| 776 // Note that we really need to do this *before* running the task, not | 779 // Note that we really need to do this *before* running the task, not |
| 777 // after. Otherwise, if more than one task is posted, the creation of the | 780 // after. Otherwise, if more than one task is posted, the creation of the |
| 778 // second thread (since we only create one at a time) will be blocked by | 781 // second thread (since we only create one at a time) will be blocked by |
| 779 // the execution of the first task, which could be arbitrarily long. | 782 // the execution of the first task, which could be arbitrarily long. |
| 780 return PrepareToStartAdditionalThreadIfHelpful(); | 783 return PrepareToStartAdditionalThreadIfHelpful(); |
| 781 } | 784 } |
| 782 | 785 |
| 783 void SequencedWorkerPool::Inner::DidRunWorkerTask(const SequencedTask& task) { | 786 void SequencedWorkerPool::Inner::DidRunWorkerTask(const SequencedTask& task) { |
| 784 lock_.AssertAcquired(); | 787 lock_.AssertAcquired(); |
| 785 | 788 |
| 786 if (task.shutdown_behavior == BLOCK_SHUTDOWN) { | 789 if (task.shutdown_behavior != CONTINUE_ON_SHUTDOWN) { |
| 787 DCHECK_GT(blocking_shutdown_thread_count_, 0u); | 790 DCHECK_GT(blocking_shutdown_thread_count_, 0u); |
| 788 blocking_shutdown_thread_count_--; | 791 blocking_shutdown_thread_count_--; |
| 789 } | 792 } |
| 790 | 793 |
| 791 if (task.sequence_token_id) | 794 if (task.sequence_token_id) |
| 792 current_sequences_.erase(task.sequence_token_id); | 795 current_sequences_.erase(task.sequence_token_id); |
| 793 } | 796 } |
| 794 | 797 |
| 795 bool SequencedWorkerPool::Inner::IsSequenceTokenRunnable( | 798 bool SequencedWorkerPool::Inner::IsSequenceTokenRunnable( |
| 796 int sequence_token_id) const { | 799 int sequence_token_id) const { |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 998 void SequencedWorkerPool::SignalHasWorkForTesting() { | 1001 void SequencedWorkerPool::SignalHasWorkForTesting() { |
| 999 inner_->SignalHasWorkForTesting(); | 1002 inner_->SignalHasWorkForTesting(); |
| 1000 } | 1003 } |
| 1001 | 1004 |
| 1002 void SequencedWorkerPool::Shutdown() { | 1005 void SequencedWorkerPool::Shutdown() { |
| 1003 DCHECK(constructor_message_loop_->BelongsToCurrentThread()); | 1006 DCHECK(constructor_message_loop_->BelongsToCurrentThread()); |
| 1004 inner_->Shutdown(); | 1007 inner_->Shutdown(); |
| 1005 } | 1008 } |
| 1006 | 1009 |
| 1007 } // namespace base | 1010 } // namespace base |
| OLD | NEW |