1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/simple_thread.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,118 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "base/simple_thread.h" 1.9 + 1.10 +#include "base/waitable_event.h" 1.11 +#include "base/logging.h" 1.12 +#include "base/platform_thread.h" 1.13 +#include "base/string_util.h" 1.14 + 1.15 +namespace base { 1.16 + 1.17 +void SimpleThread::Start() { 1.18 + DCHECK(!HasBeenStarted()) << "Tried to Start a thread multiple times."; 1.19 + bool success = PlatformThread::Create(options_.stack_size(), this, &thread_); 1.20 + CHECK(success); 1.21 + event_.Wait(); // Wait for the thread to complete initialization. 1.22 +} 1.23 + 1.24 +void SimpleThread::Join() { 1.25 + DCHECK(HasBeenStarted()) << "Tried to Join a never-started thread."; 1.26 + DCHECK(!HasBeenJoined()) << "Tried to Join a thread multiple times."; 1.27 + PlatformThread::Join(thread_); 1.28 + joined_ = true; 1.29 +} 1.30 + 1.31 +void SimpleThread::ThreadMain() { 1.32 + tid_ = PlatformThread::CurrentId(); 1.33 + // Construct our full name of the form "name_prefix_/TID". 1.34 + name_.push_back('/'); 1.35 + name_.append(IntToString(tid_)); 1.36 + PlatformThread::SetName(name_.c_str()); 1.37 + 1.38 + // We've initialized our new thread, signal that we're done to Start(). 1.39 + event_.Signal(); 1.40 + 1.41 + Run(); 1.42 +} 1.43 + 1.44 +SimpleThread::~SimpleThread() { 1.45 + DCHECK(HasBeenStarted()) << "SimpleThread was never started."; 1.46 + DCHECK(HasBeenJoined()) << "SimpleThread destroyed without being Join()ed."; 1.47 +} 1.48 + 1.49 +void DelegateSimpleThread::Run() { 1.50 + DCHECK(delegate_) << "Tried to call Run without a delegate (called twice?)"; 1.51 + delegate_->Run(); 1.52 + delegate_ = NULL; 1.53 +} 1.54 + 1.55 +DelegateSimpleThreadPool::~DelegateSimpleThreadPool() { 1.56 + DCHECK(threads_.empty()); 1.57 + DCHECK(delegates_.empty()); 1.58 + DCHECK(!dry_.IsSignaled()); 1.59 +} 1.60 + 1.61 +void DelegateSimpleThreadPool::Start() { 1.62 + DCHECK(threads_.empty()) << "Start() called with outstanding threads."; 1.63 + for (int i = 0; i < num_threads_; ++i) { 1.64 + DelegateSimpleThread* thread = new DelegateSimpleThread(this, name_prefix_); 1.65 + thread->Start(); 1.66 + threads_.push_back(thread); 1.67 + } 1.68 +} 1.69 + 1.70 +void DelegateSimpleThreadPool::JoinAll() { 1.71 + DCHECK(!threads_.empty()) << "JoinAll() called with no outstanding threads."; 1.72 + 1.73 + // Tell all our threads to quit their worker loop. 1.74 + AddWork(NULL, num_threads_); 1.75 + 1.76 + // Join and destroy all the worker threads. 1.77 + for (int i = 0; i < num_threads_; ++i) { 1.78 + threads_[i]->Join(); 1.79 + delete threads_[i]; 1.80 + } 1.81 + threads_.clear(); 1.82 + DCHECK(delegates_.empty()); 1.83 +} 1.84 + 1.85 +void DelegateSimpleThreadPool::AddWork(Delegate* delegate, int repeat_count) { 1.86 + AutoLock locked(lock_); 1.87 + for (int i = 0; i < repeat_count; ++i) 1.88 + delegates_.push(delegate); 1.89 + // If we were empty, signal that we have work now. 1.90 + if (!dry_.IsSignaled()) 1.91 + dry_.Signal(); 1.92 +} 1.93 + 1.94 +void DelegateSimpleThreadPool::Run() { 1.95 + Delegate* work; 1.96 + 1.97 + while (true) { 1.98 + dry_.Wait(); 1.99 + { 1.100 + AutoLock locked(lock_); 1.101 + if (!dry_.IsSignaled()) 1.102 + continue; 1.103 + 1.104 + DCHECK(!delegates_.empty()); 1.105 + work = delegates_.front(); 1.106 + delegates_.pop(); 1.107 + 1.108 + // Signal to any other threads that we're currently out of work. 1.109 + if (delegates_.empty()) 1.110 + dry_.Reset(); 1.111 + } 1.112 + 1.113 + // A NULL delegate pointer signals us to quit. 1.114 + if (!work) 1.115 + break; 1.116 + 1.117 + work->Run(); 1.118 + } 1.119 +} 1.120 + 1.121 +} // namespace base