|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
|
2 // Use of this source code is governed by a BSD-style license that can be |
|
3 // found in the LICENSE file. |
|
4 |
|
5 // WARNING: You should probably be using Thread (thread.h) instead. Thread is |
|
6 // Chrome's message-loop based Thread abstraction, and if you are a |
|
7 // thread running in the browser, there will likely be assumptions |
|
8 // that your thread will have an associated message loop. |
|
9 // |
|
10 // This is a simple thread interface that backs to a native operating system |
|
11 // thread. You should use this only when you want a thread that does not have |
|
12 // an associated MessageLoop. Unittesting is the best example of this. |
|
13 // |
|
14 // The simplest interface to use is DelegateSimpleThread, which will create |
|
15 // a new thread, and execute the Delegate's virtual Run() in this new thread |
|
16 // until it has completed, exiting the thread. |
|
17 // |
|
18 // NOTE: You *MUST* call Join on the thread to clean up the underlying thread |
|
19 // resources. You are also responsible for destructing the SimpleThread object. |
|
20 // It is invalid to destroy a SimpleThread while it is running, or without |
|
21 // Start() having been called (and a thread never created). The Delegate |
|
22 // object should live as long as a DelegateSimpleThread. |
|
23 // |
|
24 // Thread Safety: A SimpleThread is not completely thread safe. It is safe to |
|
25 // access it from the creating thread or from the newly created thread. This |
|
26 // implies that the creator thread should be the thread that calls Join. |
|
27 // |
|
28 // Example: |
|
29 // class MyThreadRunner : public DelegateSimpleThread::Delegate { ... }; |
|
30 // MyThreadRunner runner; |
|
31 // DelegateSimpleThread thread(&runner, "good_name_here"); |
|
32 // thread.Start(); |
|
33 // // Start will return after the Thread has been successfully started and |
|
34 // // initialized. The newly created thread will invoke runner->Run(), and |
|
35 // // run until it returns. |
|
36 // thread.Join(); // Wait until the thread has exited. You *MUST* Join! |
|
37 // // The SimpleThread object is still valid, however you may not call Join |
|
38 // // or Start again. |
|
39 |
|
40 #ifndef BASE_SIMPLE_THREAD_H_ |
|
41 #define BASE_SIMPLE_THREAD_H_ |
|
42 |
|
43 #include <string> |
|
44 #include <queue> |
|
45 #include <vector> |
|
46 |
|
47 #include "base/basictypes.h" |
|
48 #include "base/lock.h" |
|
49 #include "base/waitable_event.h" |
|
50 #include "base/platform_thread.h" |
|
51 |
|
52 namespace base { |
|
53 |
|
54 // This is the base SimpleThread. You can derive from it and implement the |
|
55 // virtual Run method, or you can use the DelegateSimpleThread interface. |
|
56 class SimpleThread : public PlatformThread::Delegate { |
|
57 public: |
|
58 class Options { |
|
59 public: |
|
60 Options() : stack_size_(0) { } |
|
61 ~Options() { } |
|
62 |
|
63 // We use the standard compiler-supplied copy constructor. |
|
64 |
|
65 // A custom stack size, or 0 for the system default. |
|
66 void set_stack_size(size_t size) { stack_size_ = size; } |
|
67 size_t stack_size() const { return stack_size_; } |
|
68 private: |
|
69 size_t stack_size_; |
|
70 }; |
|
71 |
|
72 // Create a SimpleThread. |options| should be used to manage any specific |
|
73 // configuration involving the thread creation and management. |
|
74 // Every thread has a name, in the form of |name_prefix|/TID, for example |
|
75 // "my_thread/321". The thread will not be created until Start() is called. |
|
76 explicit SimpleThread(const std::string& name_prefix) |
|
77 : name_prefix_(name_prefix), name_(name_prefix), |
|
78 thread_(), event_(true, false), tid_(0), joined_(false) { } |
|
79 SimpleThread(const std::string& name_prefix, const Options& options) |
|
80 : name_prefix_(name_prefix), name_(name_prefix), options_(options), |
|
81 thread_(), event_(true, false), tid_(0), joined_(false) { } |
|
82 |
|
83 virtual ~SimpleThread(); |
|
84 |
|
85 virtual void Start(); |
|
86 virtual void Join(); |
|
87 |
|
88 // We follow the PlatformThread Delegate interface. |
|
89 virtual void ThreadMain(); |
|
90 |
|
91 // Subclasses should override the Run method. |
|
92 virtual void Run() = 0; |
|
93 |
|
94 // Return the thread name prefix, or "unnamed" if none was supplied. |
|
95 std::string name_prefix() { return name_prefix_; } |
|
96 |
|
97 // Return the completed name including TID, only valid after Start(). |
|
98 std::string name() { return name_; } |
|
99 |
|
100 // Return the thread id, only valid after Start(). |
|
101 PlatformThreadId tid() { return tid_; } |
|
102 |
|
103 // Return True if Start() has ever been called. |
|
104 bool HasBeenStarted() { return event_.IsSignaled(); } |
|
105 |
|
106 // Return True if Join() has evern been called. |
|
107 bool HasBeenJoined() { return joined_; } |
|
108 |
|
109 private: |
|
110 const std::string name_prefix_; |
|
111 std::string name_; |
|
112 const Options options_; |
|
113 PlatformThreadHandle thread_; // PlatformThread handle, invalid after Join! |
|
114 WaitableEvent event_; // Signaled if Start() was ever called. |
|
115 PlatformThreadId tid_; // The backing thread's id. |
|
116 bool joined_; // True if Join has been called. |
|
117 }; |
|
118 |
|
119 class DelegateSimpleThread : public SimpleThread { |
|
120 public: |
|
121 class Delegate { |
|
122 public: |
|
123 Delegate() { } |
|
124 virtual ~Delegate() { } |
|
125 virtual void Run() = 0; |
|
126 }; |
|
127 |
|
128 DelegateSimpleThread(Delegate* delegate, |
|
129 const std::string& name_prefix) |
|
130 : SimpleThread(name_prefix), delegate_(delegate) { } |
|
131 DelegateSimpleThread(Delegate* delegate, |
|
132 const std::string& name_prefix, |
|
133 const Options& options) |
|
134 : SimpleThread(name_prefix, options), delegate_(delegate) { } |
|
135 |
|
136 virtual ~DelegateSimpleThread() { } |
|
137 virtual void Run(); |
|
138 private: |
|
139 Delegate* delegate_; |
|
140 }; |
|
141 |
|
142 // DelegateSimpleThreadPool allows you to start up a fixed number of threads, |
|
143 // and then add jobs which will be dispatched to the threads. This is |
|
144 // convenient when you have a lot of small work that you want done |
|
145 // multi-threaded, but don't want to spawn a thread for each small bit of work. |
|
146 // |
|
147 // You just call AddWork() to add a delegate to the list of work to be done. |
|
148 // JoinAll() will make sure that all outstanding work is processed, and wait |
|
149 // for everything to finish. You can reuse a pool, so you can call Start() |
|
150 // again after you've called JoinAll(). |
|
151 class DelegateSimpleThreadPool : public DelegateSimpleThread::Delegate { |
|
152 public: |
|
153 typedef DelegateSimpleThread::Delegate Delegate; |
|
154 |
|
155 DelegateSimpleThreadPool(const std::string name_prefix, int num_threads) |
|
156 : name_prefix_(name_prefix), num_threads_(num_threads), |
|
157 dry_(true, false) { } |
|
158 ~DelegateSimpleThreadPool(); |
|
159 |
|
160 // Start up all of the underlying threads, and start processing work if we |
|
161 // have any. |
|
162 void Start(); |
|
163 |
|
164 // Make sure all outstanding work is finished, and wait for and destroy all |
|
165 // of the underlying threads in the pool. |
|
166 void JoinAll(); |
|
167 |
|
168 // It is safe to AddWork() any time, before or after Start(). |
|
169 // Delegate* should always be a valid pointer, NULL is reserved internally. |
|
170 void AddWork(Delegate* work, int repeat_count); |
|
171 void AddWork(Delegate* work) { |
|
172 AddWork(work, 1); |
|
173 } |
|
174 |
|
175 // We implement the Delegate interface, for running our internal threads. |
|
176 virtual void Run(); |
|
177 |
|
178 private: |
|
179 const std::string name_prefix_; |
|
180 int num_threads_; |
|
181 std::vector<DelegateSimpleThread*> threads_; |
|
182 std::queue<Delegate*> delegates_; |
|
183 Lock lock_; // Locks delegates_ |
|
184 WaitableEvent dry_; // Not signaled when there is no work to do. |
|
185 }; |
|
186 |
|
187 } // namespace base |
|
188 |
|
189 #endif // BASE_SIMPLE_THREAD_H_ |