worker_pool_posix.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/worker_pool_posix.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/lazy_instance.h" 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/ref_counted.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/task.h" 123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h" 133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/worker_pool.h" 143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsennamespace base { 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kIdleSecondsBeforeExit = 10 * 60; 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A stack size of 64 KB is too small for the CERT_PKIXVerifyCert 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// function of NSS because of NSS bug 439169. 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kWorkerThreadStackSize = 128 * 1024; 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass WorkerPoolImpl { 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WorkerPoolImpl(); 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~WorkerPoolImpl(); 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void PostTask(const tracked_objects::Location& from_here, Task* task, 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool task_is_slow); 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_refptr<base::PosixDynamicThreadPool> pool_; 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottWorkerPoolImpl::WorkerPoolImpl() 373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen : pool_(new base::PosixDynamicThreadPool("WorkerPool", 383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen kIdleSecondsBeforeExit)) { 393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottWorkerPoolImpl::~WorkerPoolImpl() { 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pool_->Terminate(); 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WorkerPoolImpl::PostTask(const tracked_objects::Location& from_here, 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Task* task, bool task_is_slow) { 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott task->SetBirthPlace(from_here); 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pool_->PostTask(task); 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbase::LazyInstance<WorkerPoolImpl> g_lazy_worker_pool(base::LINKER_INITIALIZED); 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass WorkerThread : public PlatformThread::Delegate { 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WorkerThread(const std::string& name_prefix, int idle_seconds_before_exit, 5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::PosixDynamicThreadPool* pool) 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : name_prefix_(name_prefix), 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott idle_seconds_before_exit_(idle_seconds_before_exit), 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pool_(pool) {} 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ThreadMain(); 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string name_prefix_; 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const int idle_seconds_before_exit_; 6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_refptr<base::PosixDynamicThreadPool> pool_; 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(WorkerThread); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid WorkerThread::ThreadMain() { 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string name = base::StringPrintf( 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "%s/%d", name_prefix_.c_str(), PlatformThread::CurrentId()); 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThread::SetName(name.c_str()); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (;;) { 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Task* task = pool_->WaitForTask(); 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!task) 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott task->Run(); 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete task; 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The WorkerThread is non-joinable, so it deletes itself. 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete this; 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool WorkerPool::PostTask(const tracked_objects::Location& from_here, 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Task* task, bool task_is_slow) { 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_lazy_worker_pool.Pointer()->PostTask(from_here, task, task_is_slow); 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenPosixDynamicThreadPool::PosixDynamicThreadPool( 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& name_prefix, 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int idle_seconds_before_exit) 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : name_prefix_(name_prefix), 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott idle_seconds_before_exit_(idle_seconds_before_exit), 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tasks_available_cv_(&lock_), 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott num_idle_threads_(0), 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott terminated_(false), 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott num_idle_threads_cv_(NULL) {} 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenPosixDynamicThreadPool::~PosixDynamicThreadPool() { 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (!tasks_.empty()) { 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Task* task = tasks_.front(); 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tasks_.pop(); 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete task; 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid PosixDynamicThreadPool::Terminate() { 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AutoLock locked(lock_); 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!terminated_) << "Thread pool is already terminated."; 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott terminated_ = true; 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tasks_available_cv_.Broadcast(); 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid PosixDynamicThreadPool::PostTask(Task* task) { 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AutoLock locked(lock_); 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!terminated_) << 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "This thread pool is already terminated. Do not post new tasks."; 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tasks_.push(task); 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We have enough worker threads. 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (static_cast<size_t>(num_idle_threads_) >= tasks_.size()) { 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tasks_available_cv_.Signal(); 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The new PlatformThread will take ownership of the WorkerThread object, 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // which will delete itself on exit. 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WorkerThread* worker = 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new WorkerThread(name_prefix_, idle_seconds_before_exit_, this); 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThread::CreateNonJoinable(kWorkerThreadStackSize, worker); 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenTask* PosixDynamicThreadPool::WaitForTask() { 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AutoLock locked(lock_); 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (terminated_) 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (tasks_.empty()) { // No work available, wait for work. 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott num_idle_threads_++; 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (num_idle_threads_cv_.get()) 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott num_idle_threads_cv_->Signal(); 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tasks_available_cv_.TimedWait( 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeDelta::FromSeconds(kIdleSecondsBeforeExit)); 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott num_idle_threads_--; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (num_idle_threads_cv_.get()) 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott num_idle_threads_cv_->Signal(); 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (tasks_.empty()) { 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We waited for work, but there's still no work. Return NULL to signal 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the thread to terminate. 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Task* task = tasks_.front(); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tasks_.pop(); 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return task; 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 170