1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/simple_thread.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,189 @@ 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 +// WARNING: You should probably be using Thread (thread.h) instead. Thread is 1.9 +// Chrome's message-loop based Thread abstraction, and if you are a 1.10 +// thread running in the browser, there will likely be assumptions 1.11 +// that your thread will have an associated message loop. 1.12 +// 1.13 +// This is a simple thread interface that backs to a native operating system 1.14 +// thread. You should use this only when you want a thread that does not have 1.15 +// an associated MessageLoop. Unittesting is the best example of this. 1.16 +// 1.17 +// The simplest interface to use is DelegateSimpleThread, which will create 1.18 +// a new thread, and execute the Delegate's virtual Run() in this new thread 1.19 +// until it has completed, exiting the thread. 1.20 +// 1.21 +// NOTE: You *MUST* call Join on the thread to clean up the underlying thread 1.22 +// resources. You are also responsible for destructing the SimpleThread object. 1.23 +// It is invalid to destroy a SimpleThread while it is running, or without 1.24 +// Start() having been called (and a thread never created). The Delegate 1.25 +// object should live as long as a DelegateSimpleThread. 1.26 +// 1.27 +// Thread Safety: A SimpleThread is not completely thread safe. It is safe to 1.28 +// access it from the creating thread or from the newly created thread. This 1.29 +// implies that the creator thread should be the thread that calls Join. 1.30 +// 1.31 +// Example: 1.32 +// class MyThreadRunner : public DelegateSimpleThread::Delegate { ... }; 1.33 +// MyThreadRunner runner; 1.34 +// DelegateSimpleThread thread(&runner, "good_name_here"); 1.35 +// thread.Start(); 1.36 +// // Start will return after the Thread has been successfully started and 1.37 +// // initialized. The newly created thread will invoke runner->Run(), and 1.38 +// // run until it returns. 1.39 +// thread.Join(); // Wait until the thread has exited. You *MUST* Join! 1.40 +// // The SimpleThread object is still valid, however you may not call Join 1.41 +// // or Start again. 1.42 + 1.43 +#ifndef BASE_SIMPLE_THREAD_H_ 1.44 +#define BASE_SIMPLE_THREAD_H_ 1.45 + 1.46 +#include <string> 1.47 +#include <queue> 1.48 +#include <vector> 1.49 + 1.50 +#include "base/basictypes.h" 1.51 +#include "base/lock.h" 1.52 +#include "base/waitable_event.h" 1.53 +#include "base/platform_thread.h" 1.54 + 1.55 +namespace base { 1.56 + 1.57 +// This is the base SimpleThread. You can derive from it and implement the 1.58 +// virtual Run method, or you can use the DelegateSimpleThread interface. 1.59 +class SimpleThread : public PlatformThread::Delegate { 1.60 + public: 1.61 + class Options { 1.62 + public: 1.63 + Options() : stack_size_(0) { } 1.64 + ~Options() { } 1.65 + 1.66 + // We use the standard compiler-supplied copy constructor. 1.67 + 1.68 + // A custom stack size, or 0 for the system default. 1.69 + void set_stack_size(size_t size) { stack_size_ = size; } 1.70 + size_t stack_size() const { return stack_size_; } 1.71 + private: 1.72 + size_t stack_size_; 1.73 + }; 1.74 + 1.75 + // Create a SimpleThread. |options| should be used to manage any specific 1.76 + // configuration involving the thread creation and management. 1.77 + // Every thread has a name, in the form of |name_prefix|/TID, for example 1.78 + // "my_thread/321". The thread will not be created until Start() is called. 1.79 + explicit SimpleThread(const std::string& name_prefix) 1.80 + : name_prefix_(name_prefix), name_(name_prefix), 1.81 + thread_(), event_(true, false), tid_(0), joined_(false) { } 1.82 + SimpleThread(const std::string& name_prefix, const Options& options) 1.83 + : name_prefix_(name_prefix), name_(name_prefix), options_(options), 1.84 + thread_(), event_(true, false), tid_(0), joined_(false) { } 1.85 + 1.86 + virtual ~SimpleThread(); 1.87 + 1.88 + virtual void Start(); 1.89 + virtual void Join(); 1.90 + 1.91 + // We follow the PlatformThread Delegate interface. 1.92 + virtual void ThreadMain(); 1.93 + 1.94 + // Subclasses should override the Run method. 1.95 + virtual void Run() = 0; 1.96 + 1.97 + // Return the thread name prefix, or "unnamed" if none was supplied. 1.98 + std::string name_prefix() { return name_prefix_; } 1.99 + 1.100 + // Return the completed name including TID, only valid after Start(). 1.101 + std::string name() { return name_; } 1.102 + 1.103 + // Return the thread id, only valid after Start(). 1.104 + PlatformThreadId tid() { return tid_; } 1.105 + 1.106 + // Return True if Start() has ever been called. 1.107 + bool HasBeenStarted() { return event_.IsSignaled(); } 1.108 + 1.109 + // Return True if Join() has evern been called. 1.110 + bool HasBeenJoined() { return joined_; } 1.111 + 1.112 + private: 1.113 + const std::string name_prefix_; 1.114 + std::string name_; 1.115 + const Options options_; 1.116 + PlatformThreadHandle thread_; // PlatformThread handle, invalid after Join! 1.117 + WaitableEvent event_; // Signaled if Start() was ever called. 1.118 + PlatformThreadId tid_; // The backing thread's id. 1.119 + bool joined_; // True if Join has been called. 1.120 +}; 1.121 + 1.122 +class DelegateSimpleThread : public SimpleThread { 1.123 + public: 1.124 + class Delegate { 1.125 + public: 1.126 + Delegate() { } 1.127 + virtual ~Delegate() { } 1.128 + virtual void Run() = 0; 1.129 + }; 1.130 + 1.131 + DelegateSimpleThread(Delegate* delegate, 1.132 + const std::string& name_prefix) 1.133 + : SimpleThread(name_prefix), delegate_(delegate) { } 1.134 + DelegateSimpleThread(Delegate* delegate, 1.135 + const std::string& name_prefix, 1.136 + const Options& options) 1.137 + : SimpleThread(name_prefix, options), delegate_(delegate) { } 1.138 + 1.139 + virtual ~DelegateSimpleThread() { } 1.140 + virtual void Run(); 1.141 + private: 1.142 + Delegate* delegate_; 1.143 +}; 1.144 + 1.145 +// DelegateSimpleThreadPool allows you to start up a fixed number of threads, 1.146 +// and then add jobs which will be dispatched to the threads. This is 1.147 +// convenient when you have a lot of small work that you want done 1.148 +// multi-threaded, but don't want to spawn a thread for each small bit of work. 1.149 +// 1.150 +// You just call AddWork() to add a delegate to the list of work to be done. 1.151 +// JoinAll() will make sure that all outstanding work is processed, and wait 1.152 +// for everything to finish. You can reuse a pool, so you can call Start() 1.153 +// again after you've called JoinAll(). 1.154 +class DelegateSimpleThreadPool : public DelegateSimpleThread::Delegate { 1.155 + public: 1.156 + typedef DelegateSimpleThread::Delegate Delegate; 1.157 + 1.158 + DelegateSimpleThreadPool(const std::string name_prefix, int num_threads) 1.159 + : name_prefix_(name_prefix), num_threads_(num_threads), 1.160 + dry_(true, false) { } 1.161 + ~DelegateSimpleThreadPool(); 1.162 + 1.163 + // Start up all of the underlying threads, and start processing work if we 1.164 + // have any. 1.165 + void Start(); 1.166 + 1.167 + // Make sure all outstanding work is finished, and wait for and destroy all 1.168 + // of the underlying threads in the pool. 1.169 + void JoinAll(); 1.170 + 1.171 + // It is safe to AddWork() any time, before or after Start(). 1.172 + // Delegate* should always be a valid pointer, NULL is reserved internally. 1.173 + void AddWork(Delegate* work, int repeat_count); 1.174 + void AddWork(Delegate* work) { 1.175 + AddWork(work, 1); 1.176 + } 1.177 + 1.178 + // We implement the Delegate interface, for running our internal threads. 1.179 + virtual void Run(); 1.180 + 1.181 + private: 1.182 + const std::string name_prefix_; 1.183 + int num_threads_; 1.184 + std::vector<DelegateSimpleThread*> threads_; 1.185 + std::queue<Delegate*> delegates_; 1.186 + Lock lock_; // Locks delegates_ 1.187 + WaitableEvent dry_; // Not signaled when there is no work to do. 1.188 +}; 1.189 + 1.190 +} // namespace base 1.191 + 1.192 +#endif // BASE_SIMPLE_THREAD_H_