Index: base/threading/sequenced_worker_pool.cc |
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc |
index 52b178bcd5f42be4a71d45b692d5e879b033bf04..6f4a248aaf6cd2a0492f45c3647258f05c20fc31 100644 |
--- a/base/threading/sequenced_worker_pool.cc |
+++ b/base/threading/sequenced_worker_pool.cc |
@@ -239,24 +239,41 @@ class SequencedWorkerPool::Worker : public SimpleThread { |
// SimpleThread implementation. This actually runs the background thread. |
void Run() override; |
+ // Indicates that a task is about to be run. The parameters provide |
+ // additional metainformation about the task being run. |
void set_running_task_info(SequenceToken token, |
WorkerShutdown shutdown_behavior) { |
- running_sequence_ = token; |
- running_shutdown_behavior_ = shutdown_behavior; |
+ is_processing_task_ = true; |
+ task_sequence_token_ = token; |
+ task_shutdown_behavior_ = shutdown_behavior; |
} |
- SequenceToken running_sequence() const { |
- return running_sequence_; |
+ // Indicates that the task has finished running. |
+ void reset_running_task_info() { is_processing_task_ = false; } |
+ |
+ // Whether the worker is processing a task. |
+ bool is_processing_task() { return is_processing_task_; } |
+ |
+ SequenceToken task_sequence_token() const { |
+ DCHECK(is_processing_task_); |
+ return task_sequence_token_; |
} |
- WorkerShutdown running_shutdown_behavior() const { |
- return running_shutdown_behavior_; |
+ WorkerShutdown task_shutdown_behavior() const { |
+ DCHECK(is_processing_task_); |
+ return task_shutdown_behavior_; |
} |
private: |
scoped_refptr<SequencedWorkerPool> worker_pool_; |
- SequenceToken running_sequence_; |
- WorkerShutdown running_shutdown_behavior_; |
+ // The sequence token of the task being processed. Only valid when |
+ // is_processing_task_ is true. |
+ SequenceToken task_sequence_token_; |
+ // The shutdown behavior of the task being processed. Only valid when |
+ // is_processing_task_ is true. |
+ WorkerShutdown task_shutdown_behavior_; |
+ // Whether the Worker is processing a task. |
+ bool is_processing_task_; |
DISALLOW_COPY_AND_ASSIGN(Worker); |
}; |
@@ -326,11 +343,6 @@ class SequencedWorkerPool::Inner { |
// Called from within the lock, this returns the next sequence task number. |
int64 LockedGetNextSequenceTaskNumber(); |
- // Called from within the lock, returns the shutdown behavior of the task |
- // running on the currently executing worker thread. If invoked from a thread |
- // that is not one of the workers, returns CONTINUE_ON_SHUTDOWN. |
- WorkerShutdown LockedCurrentThreadShutdownBehavior() const; |
- |
// Gets new task. There are 3 cases depending on the return value: |
// |
// 1) If the return value is |GET_WORK_FOUND|, |task| is filled in and should |
@@ -483,7 +495,8 @@ SequencedWorkerPool::Worker::Worker( |
const std::string& prefix) |
: SimpleThread(prefix + StringPrintf("Worker%d", thread_number)), |
worker_pool_(worker_pool), |
- running_shutdown_behavior_(CONTINUE_ON_SHUTDOWN) { |
+ task_shutdown_behavior_(BLOCK_SHUTDOWN), |
+ is_processing_task_(false) { |
Start(); |
} |
@@ -497,7 +510,7 @@ void SequencedWorkerPool::Worker::Run() { |
// Store a pointer to the running sequence in thread local storage for |
// static function access. |
- g_lazy_tls_ptr.Get().Set(&running_sequence_); |
+ g_lazy_tls_ptr.Get().Set(&task_sequence_token_); |
// Just jump back to the Inner object to run the thread, since it has all the |
// tracking information and queues. It might be more natural to implement |
@@ -583,10 +596,19 @@ bool SequencedWorkerPool::Inner::PostTask( |
{ |
AutoLock lock(lock_); |
if (shutdown_called_) { |
- if (shutdown_behavior != BLOCK_SHUTDOWN || |
- LockedCurrentThreadShutdownBehavior() == CONTINUE_ON_SHUTDOWN) { |
+ // Don't allow a new task to be posted if it doesn't block shutdown. |
+ if (shutdown_behavior != BLOCK_SHUTDOWN) |
+ return false; |
+ |
+ // If the current thread is running a task, and that task doesn't block |
+ // shutdown, then it shouldn't be allowed to post any more tasks. |
+ ThreadMap::const_iterator found = |
+ threads_.find(PlatformThread::CurrentId()); |
+ if (found != threads_.end() && found->second->is_processing_task() && |
+ found->second->task_shutdown_behavior() != BLOCK_SHUTDOWN) { |
return false; |
} |
+ |
if (max_blocking_tasks_after_shutdown_ <= 0) { |
DLOG(WARNING) << "BLOCK_SHUTDOWN task disallowed"; |
return false; |
@@ -635,7 +657,8 @@ bool SequencedWorkerPool::Inner::IsRunningSequenceOnCurrentThread( |
ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId()); |
if (found == threads_.end()) |
return false; |
- return sequence_token.Equals(found->second->running_sequence()); |
+ return found->second->is_processing_task() && |
+ sequence_token.Equals(found->second->task_sequence_token()); |
} |
// See https://code.google.com/p/chromium/issues/detail?id=168415 |
@@ -765,13 +788,12 @@ void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) { |
// Make sure our task is erased outside the lock for the |
// same reason we do this with delete_these_oustide_lock. |
- // Also, do it before calling set_running_task_info() so |
+ // Also, do it before calling reset_running_task_info() so |
// that sequence-checking from within the task's destructor |
// still works. |
task.task = Closure(); |
- this_worker->set_running_task_info( |
- SequenceToken(), CONTINUE_ON_SHUTDOWN); |
+ this_worker->reset_running_task_info(); |
} |
DidRunWorkerTask(task); // Must be done inside the lock. |
} else if (cleanup_state_ == CLEANUP_RUNNING) { |
@@ -904,15 +926,6 @@ int64 SequencedWorkerPool::Inner::LockedGetNextSequenceTaskNumber() { |
return next_sequence_task_number_++; |
} |
-SequencedWorkerPool::WorkerShutdown |
-SequencedWorkerPool::Inner::LockedCurrentThreadShutdownBehavior() const { |
- lock_.AssertAcquired(); |
- ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId()); |
- if (found == threads_.end()) |
- return CONTINUE_ON_SHUTDOWN; |
- return found->second->running_shutdown_behavior(); |
-} |
- |
SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork( |
SequencedTask* task, |
TimeDelta* wait_time, |