13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// 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/simple_thread.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 83f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base { 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSimpleThread::SimpleThread(const std::string& name_prefix) 1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : name_prefix_(name_prefix), name_(name_prefix), 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen thread_(), event_(true, false), tid_(0), joined_(false) { 1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSimpleThread::SimpleThread(const std::string& name_prefix, 1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const Options& options) 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : name_prefix_(name_prefix), name_(name_prefix), options_(options), 2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen thread_(), event_(true, false), tid_(0), joined_(false) { 2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSimpleThread::~SimpleThread() { 2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(HasBeenStarted()) << "SimpleThread was never started."; 2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(HasBeenJoined()) << "SimpleThread destroyed without being Join()ed."; 2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SimpleThread::Start() { 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!HasBeenStarted()) << "Tried to Start a thread multiple times."; 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool success = PlatformThread::Create(options_.stack_size(), this, &thread_); 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK(success); 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_.Wait(); // Wait for the thread to complete initialization. 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SimpleThread::Join() { 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(HasBeenStarted()) << "Tried to Join a never-started thread."; 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!HasBeenJoined()) << "Tried to Join a thread multiple times."; 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThread::Join(thread_); 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott joined_ = true; 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SimpleThread::ThreadMain() { 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tid_ = PlatformThread::CurrentId(); 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Construct our full name of the form "name_prefix_/TID". 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name_.push_back('/'); 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name_.append(IntToString(tid_)); 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PlatformThread::SetName(name_.c_str()); 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We've initialized our new thread, signal that we're done to Start(). 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_.Signal(); 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Run(); 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 56731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickDelegateSimpleThread::DelegateSimpleThread(Delegate* delegate, 57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& name_prefix) 58731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : SimpleThread(name_prefix), 59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick delegate_(delegate) { 60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 62731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickDelegateSimpleThread::DelegateSimpleThread(Delegate* delegate, 63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& name_prefix, 64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const Options& options) 65731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : SimpleThread(name_prefix, options), 66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick delegate_(delegate) { 67731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 69731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickDelegateSimpleThread::~DelegateSimpleThread() { 70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DelegateSimpleThread::Run() { 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(delegate_) << "Tried to call Run without a delegate (called twice?)"; 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_->Run(); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegate_ = NULL; 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickDelegateSimpleThreadPool::DelegateSimpleThreadPool( 79731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& name_prefix, 80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int num_threads) 81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : name_prefix_(name_prefix), 82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick num_threads_(num_threads), 83731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick dry_(true, false) { 84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottDelegateSimpleThreadPool::~DelegateSimpleThreadPool() { 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(threads_.empty()); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(delegates_.empty()); 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!dry_.IsSignaled()); 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DelegateSimpleThreadPool::Start() { 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(threads_.empty()) << "Start() called with outstanding threads."; 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < num_threads_; ++i) { 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DelegateSimpleThread* thread = new DelegateSimpleThread(this, name_prefix_); 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott thread->Start(); 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott threads_.push_back(thread); 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DelegateSimpleThreadPool::JoinAll() { 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!threads_.empty()) << "JoinAll() called with no outstanding threads."; 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Tell all our threads to quit their worker loop. 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddWork(NULL, num_threads_); 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Join and destroy all the worker threads. 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < num_threads_; ++i) { 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott threads_[i]->Join(); 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete threads_[i]; 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott threads_.clear(); 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(delegates_.empty()); 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DelegateSimpleThreadPool::AddWork(Delegate* delegate, int repeat_count) { 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AutoLock locked(lock_); 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < repeat_count; ++i) 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegates_.push(delegate); 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If we were empty, signal that we have work now. 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!dry_.IsSignaled()) 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dry_.Signal(); 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DelegateSimpleThreadPool::Run() { 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Delegate* work = NULL; 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (true) { 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dry_.Wait(); 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AutoLock locked(lock_); 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!dry_.IsSignaled()) 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!delegates_.empty()); 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott work = delegates_.front(); 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delegates_.pop(); 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Signal to any other threads that we're currently out of work. 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delegates_.empty()) 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dry_.Reset(); 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // A NULL delegate pointer signals us to quit. 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!work) 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott work->Run(); 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 153