Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3099)

Unified Diff: base/tracked_objects.cc

Issue 8597017: Switch to a simple linked-list for worker thread pool (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« base/tracked_objects.h ('K') | « base/tracked_objects.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/tracked_objects.cc
===================================================================
--- base/tracked_objects.cc (revision 110706)
+++ base/tracked_objects.cc (working copy)
@@ -135,7 +135,7 @@
ThreadData* ThreadData::all_thread_data_list_head_ = NULL;
// static
-ThreadData::ThreadDataPool* ThreadData::unregistered_thread_data_pool_ = NULL;
+ThreadData* ThreadData::first_retired_worker_ = NULL;
// static
base::LazyInstance<base::Lock,
@@ -148,18 +148,20 @@
ThreadData::ThreadData(const std::string& suggested_name)
: incarnation_count_for_pool_(-1),
next_(NULL),
+ next_retired_worker_(NULL),
worker_thread_number_(0) {
DCHECK_GE(suggested_name.size(), 0u);
thread_name_ = suggested_name;
PushToHeadOfList(); // Which sets real incarnation_count_for_pool_.
}
-ThreadData::ThreadData(size_t thread_number)
+ThreadData::ThreadData(int thread_number)
: incarnation_count_for_pool_(-1),
next_(NULL),
+ next_retired_worker_(NULL),
worker_thread_number_(thread_number) {
- CHECK_NE(thread_number, 0u);
- base::StringAppendF(&thread_name_, "WorkerThread-%"PRIuS, thread_number);
+ CHECK_GT(thread_number, 0);
+ base::StringAppendF(&thread_name_, "WorkerThread-%d", thread_number);
PushToHeadOfList(); // Which sets real incarnation_count_for_pool_.
}
@@ -195,25 +197,22 @@
// We must be a worker thread, since we didn't pre-register.
ThreadData* worker_thread_data = NULL;
- size_t thread_number = 0;
+ int thread_number = 0;
{
base::AutoLock lock(*list_lock_.Pointer());
- if (!unregistered_thread_data_pool_)
- unregistered_thread_data_pool_ = new ThreadDataPool;
- if (!unregistered_thread_data_pool_->empty()) {
- worker_thread_data =
- const_cast<ThreadData*>(unregistered_thread_data_pool_->top());
- unregistered_thread_data_pool_->pop();
+ if (first_retired_worker_) {
+ worker_thread_data = first_retired_worker_;
+ first_retired_worker_ = first_retired_worker_->next_retired_worker_;
+ worker_thread_data->next_retired_worker_ = NULL;
} else {
thread_number = ++thread_number_counter_;
- unregistered_thread_data_pool_->reserve(thread_number);
}
}
// If we can't find a previously used instance, then we have to create one.
if (!worker_thread_data)
worker_thread_data = new ThreadData(thread_number);
- DCHECK_GT(worker_thread_data->worker_thread_number_, 0u);
+ DCHECK_GT(worker_thread_data->worker_thread_number_, 0);
tls_index_.Set(worker_thread_data);
return worker_thread_data;
@@ -228,14 +227,17 @@
reinterpret_cast<ThreadData*>(thread_data)->OnThreadTerminationCleanup();
}
-void ThreadData::OnThreadTerminationCleanup() const {
+void ThreadData::OnThreadTerminationCleanup() {
if (!worker_thread_number_)
return;
base::AutoLock lock(*list_lock_.Pointer());
if (incarnation_counter_ != incarnation_count_for_pool_)
return; // ThreadData was constructed in an earlier unit test.
- // The following will never have to do an allocation.
- unregistered_thread_data_pool_->push(this);
+ // We must NOT do any allocations during this callback.
+ // Using the simple linked lists avoids all allocations.
+ DCHECK_EQ(this->next_retired_worker_, reinterpret_cast<ThreadData*>(NULL));
+ this->next_retired_worker_ = first_retired_worker_;
+ first_retired_worker_ = this;
}
// static
@@ -512,14 +514,18 @@
if (!InitializeAndSetTrackingStatus(false))
return;
ThreadData* thread_data_list;
- ThreadDataPool* final_pool;
{
base::AutoLock lock(*list_lock_.Pointer());
thread_data_list = all_thread_data_list_head_;
all_thread_data_list_head_ = NULL;
- final_pool = unregistered_thread_data_pool_;
- unregistered_thread_data_pool_ = NULL;
++incarnation_counter_;
+ // To be clean, break apart the retired worker list (though we leak them).
+ while(first_retired_worker_) {
+ ThreadData* worker = first_retired_worker_;
+ CHECK_GT(worker->worker_thread_number_, 0);
+ first_retired_worker_ = worker->next_retired_worker_;
+ worker->next_retired_worker_ = NULL;
+ }
}
// Put most global static back in pristine shape.
@@ -535,15 +541,6 @@
// When we want to cleanup (on a single thread), here is what we do.
- if (final_pool) {
- // The thread_data_list contains *all* the instances, and we'll use it to
- // delete them. This pool has pointers to some instances, and we just
- // have to drop those pointers (and not do the deletes here).
- while (!final_pool->empty())
- final_pool->pop();
- delete final_pool;
- }
-
// Do actual recursive delete in all ThreadData instances.
while (thread_data_list) {
ThreadData* next_thread_data = thread_data_list;
@@ -559,49 +556,6 @@
}
//------------------------------------------------------------------------------
-// Small partial implementation of a stack that never has to allocate during a
-// push() operation, because it is always prepared to accept the maximum number
-// of ThreadData instances (all the worker thread related instances).
-
-ThreadData::ThreadDataPool::ThreadDataPool() : empty_slot_(0) {};
-ThreadData::ThreadDataPool::~ThreadDataPool() {};
-
-bool ThreadData::ThreadDataPool::empty() const { return empty_slot_ == 0; }
-
-void ThreadData::ThreadDataPool::reserve(size_t largest_worker_pool_number) {
- // Worker pool numbers start at 1, and exclude 0, so the number is exactly
- // the least size needed.
- // Due to asynchronous construction of worker-pool numbers (and associated
- // ThreadData), we might not hear about the numbers sequentially.
- if (largest_worker_pool_number > stack_.size())
- stack_.resize(largest_worker_pool_number);
-}
-
-const ThreadData* ThreadData::ThreadDataPool::top() const {
- if (empty_slot_ > 0)
- return stack_[empty_slot_ - 1];
- NOTREACHED();
- return NULL;
-}
-
-void ThreadData::ThreadDataPool::push(const ThreadData* thread_data) {
- if (empty_slot_ < stack_.size()) {
- stack_[empty_slot_] = thread_data;
- ++empty_slot_;
- return;
- }
- NOTREACHED();
-}
-
-void ThreadData::ThreadDataPool::pop() {
- if (empty_slot_ > 0) {
- --empty_slot_;
- return;
- }
- NOTREACHED();
-}
-
-//------------------------------------------------------------------------------
// Individual 3-tuple of birth (place and thread) along with death thread, and
// the accumulated stats for instances (DeathData).
« base/tracked_objects.h ('K') | « base/tracked_objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698