| Index: base/threading/sequenced_worker_pool.cc
|
| diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc
|
| index f98b23d5d6168a818178fe0c2e0a777edd618bd5..584e1f4b2a84d66ced9f53aa9cb50d8007276278 100644
|
| --- a/base/threading/sequenced_worker_pool.cc
|
| +++ b/base/threading/sequenced_worker_pool.cc
|
| @@ -15,16 +15,17 @@
|
| #include "base/compiler_specific.h"
|
| #include "base/critical_closure.h"
|
| #include "base/debug/trace_event.h"
|
| +#include "base/lazy_instance.h"
|
| #include "base/logging.h"
|
| #include "base/memory/linked_ptr.h"
|
| #include "base/message_loop/message_loop_proxy.h"
|
| -#include "base/metrics/histogram.h"
|
| #include "base/stl_util.h"
|
| #include "base/strings/stringprintf.h"
|
| #include "base/synchronization/condition_variable.h"
|
| #include "base/synchronization/lock.h"
|
| #include "base/threading/platform_thread.h"
|
| #include "base/threading/simple_thread.h"
|
| +#include "base/threading/thread_local.h"
|
| #include "base/threading/thread_restrictions.h"
|
| #include "base/time/time.h"
|
| #include "base/tracked_objects.h"
|
| @@ -33,10 +34,17 @@
|
| #include "base/mac/scoped_nsautorelease_pool.h"
|
| #endif
|
|
|
| +#if !defined(OS_NACL)
|
| +#include "base/metrics/histogram.h"
|
| +#endif
|
| +
|
| namespace base {
|
|
|
| namespace {
|
|
|
| +base::LazyInstance<base::ThreadLocalPointer<SequencedWorkerPool> >
|
| + lazy_tls_ptr = LAZY_INSTANCE_INITIALIZER;
|
| +
|
| struct SequencedTask : public TrackingInfo {
|
| SequencedTask()
|
| : sequence_token_id(0),
|
| @@ -267,6 +275,8 @@ class SequencedWorkerPool::Inner {
|
|
|
| SequenceToken GetNamedSequenceToken(const std::string& name);
|
|
|
| + bool GetCurrentThreadSequenceToken(SequenceToken* result_token) const;
|
| +
|
| // This function accepts a name and an ID. If the name is null, the
|
| // token ID is used. This allows us to implement the optional name lookup
|
| // from a single function without having to enter the lock a separate time.
|
| @@ -479,6 +489,9 @@ SequencedWorkerPool::Worker::~Worker() {
|
| }
|
|
|
| void SequencedWorkerPool::Worker::Run() {
|
| + // Store the SequencedWorkerPool associated with this worker thread.
|
| + lazy_tls_ptr.Get().Set(worker_pool_.get());
|
| +
|
| // 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
|
| // using DelegateSimpleThread and have Inner implement the Delegate to avoid
|
| @@ -543,6 +556,17 @@ SequencedWorkerPool::Inner::GetNamedSequenceToken(const std::string& name) {
|
| return SequenceToken(LockedGetNamedTokenID(name));
|
| }
|
|
|
| +bool SequencedWorkerPool::Inner::GetCurrentThreadSequenceToken(
|
| + SequenceToken* result_token) const {
|
| + DCHECK(result_token);
|
| + AutoLock lock(lock_);
|
| + ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId());
|
| + if (found == threads_.end())
|
| + return false;
|
| + *result_token = found->second->running_sequence();
|
| + return true;
|
| +}
|
| +
|
| bool SequencedWorkerPool::Inner::PostTask(
|
| const std::string* optional_token_name,
|
| SequenceToken sequence_token,
|
| @@ -611,11 +635,10 @@ bool SequencedWorkerPool::Inner::RunsTasksOnCurrentThread() const {
|
|
|
| bool SequencedWorkerPool::Inner::IsRunningSequenceOnCurrentThread(
|
| SequenceToken sequence_token) const {
|
| - AutoLock lock(lock_);
|
| - ThreadMap::const_iterator found = threads_.find(PlatformThread::CurrentId());
|
| - if (found == threads_.end())
|
| + SequenceToken current_thread_token;
|
| + if (!GetCurrentThreadSequenceToken(¤t_thread_token))
|
| return false;
|
| - return found->second->running_sequence().Equals(sequence_token);
|
| + return current_thread_token.Equals(sequence_token);
|
| }
|
|
|
| // See https://code.google.com/p/chromium/issues/detail?id=168415
|
| @@ -674,8 +697,10 @@ void SequencedWorkerPool::Inner::Shutdown(
|
| while (!CanShutdown())
|
| can_shutdown_cv_.Wait();
|
| }
|
| +#if !defined(OS_NACL)
|
| UMA_HISTOGRAM_TIMES("SequencedWorkerPool.ShutdownDelayTime",
|
| TimeTicks::Now() - shutdown_wait_begin);
|
| +#endif
|
| }
|
|
|
| void SequencedWorkerPool::Inner::ThreadLoop(Worker* this_worker) {
|
| @@ -872,8 +897,10 @@ SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork(
|
| std::vector<Closure>* delete_these_outside_lock) {
|
| lock_.AssertAcquired();
|
|
|
| +#if !defined(OS_NACL)
|
| UMA_HISTOGRAM_COUNTS_100("SequencedWorkerPool.TaskCount",
|
| static_cast<int>(pending_tasks_.size()));
|
| +#endif
|
|
|
| // Find the next task with a sequence token that's not currently in use.
|
| // If the token is in use, that means another thread is running something
|
| @@ -958,8 +985,10 @@ SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork(
|
| // Track the number of tasks we had to skip over to see if we should be
|
| // making this more efficient. If this number ever becomes large or is
|
| // frequently "some", we should consider the optimization above.
|
| +#if !defined(OS_NACL)
|
| UMA_HISTOGRAM_COUNTS_100("SequencedWorkerPool.UnrunnableTaskCount",
|
| unrunnable_tasks);
|
| +#endif
|
| return status;
|
| }
|
|
|
| @@ -1090,6 +1119,11 @@ bool SequencedWorkerPool::Inner::CanShutdown() const {
|
|
|
| // SequencedWorkerPool --------------------------------------------------------
|
|
|
| +// static
|
| +SequencedWorkerPool* SequencedWorkerPool::Current() {
|
| + return lazy_tls_ptr.Get().Get();
|
| +}
|
| +
|
| SequencedWorkerPool::SequencedWorkerPool(
|
| size_t max_threads,
|
| const std::string& thread_name_prefix)
|
| @@ -1127,6 +1161,11 @@ SequencedWorkerPool::SequenceToken SequencedWorkerPool::GetNamedSequenceToken(
|
| return inner_->GetNamedSequenceToken(name);
|
| }
|
|
|
| +bool SequencedWorkerPool::GetCurrentThreadSequenceToken(
|
| + SequenceToken* result_token) const {
|
| + return inner_->GetCurrentThreadSequenceToken(result_token);
|
| +}
|
| +
|
| scoped_refptr<SequencedTaskRunner> SequencedWorkerPool::GetSequencedTaskRunner(
|
| SequenceToken token) {
|
| return GetSequencedTaskRunnerWithShutdownBehavior(token, BLOCK_SHUTDOWN);
|
|
|