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..22883a8a49aa09f9a8a8b3152e718732bd5dd7d6 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()); |
darin (slow to review)
2013/07/02 13:54:23
Why do we need TLS to find the owner and this map
tommycli
2013/07/02 17:22:58
Sequence tokens are assigned from positive integer
|
+ 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; |
} |
@@ -1127,6 +1156,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); |
@@ -1236,4 +1270,9 @@ void SequencedWorkerPool::Shutdown(int max_new_blocking_tasks_after_shutdown) { |
inner_->Shutdown(max_new_blocking_tasks_after_shutdown); |
} |
+// static |
+SequencedWorkerPool* SequencedWorkerPool::Owner() { |
+ return lazy_tls_ptr.Get().Get(); |
+} |
+ |
} // namespace base |