blob: 7d6fef75a92c073383b5437806456ec0d6253eba [file] [log] [blame]
Marc Slemko66949872006-07-15 01:52:39 +00001#include "ThreadManager.h"
Marc Slemkod466b212006-07-20 00:04:18 +00002#include "Exception.h"
Marc Slemko0e53ccd2006-07-17 23:51:05 +00003#include "Monitor.h"
Marc Slemko66949872006-07-15 01:52:39 +00004
Marc Slemko6f038a72006-08-03 18:58:09 +00005#include <boost/shared_ptr.hpp>
6
Marc Slemko66949872006-07-15 01:52:39 +00007#include <assert.h>
Marc Slemko0e53ccd2006-07-17 23:51:05 +00008#include <queue>
9#include <set>
Marc Slemko66949872006-07-15 01:52:39 +000010
Marc Slemko6f038a72006-08-03 18:58:09 +000011#if defined(DEBUG)
12#include <iostream>
13#endif //defined(DEBUG)
14
Marc Slemko66949872006-07-15 01:52:39 +000015namespace facebook { namespace thrift { namespace concurrency {
16
Marc Slemko6f038a72006-08-03 18:58:09 +000017using namespace boost;
18
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000019
Mark Sleef5f2be42006-09-05 21:05:31 +000020/**
21 * ThreadManager class
22 *
23 * This class manages a pool of threads. It uses a ThreadFactory to create
24 * threads. It never actually creates or destroys worker threads, rather
25 * it maintains statistics on number of idle threads, number of active threads,
26 * task backlog, and average wait and service times.
27 *
28 * @author marc
29 * @version $Id:$
30 */
Marc Slemko0e53ccd2006-07-17 23:51:05 +000031class ThreadManager::Impl : public ThreadManager {
32
33 public:
Marc Slemko6f038a72006-08-03 18:58:09 +000034 Impl() :
35 _workerCount(0),
36 _workerMaxCount(0),
37 _idleCount(0),
Mark Sleef5f2be42006-09-05 21:05:31 +000038 _state(ThreadManager::UNINITIALIZED) {}
Marc Slemkod466b212006-07-20 00:04:18 +000039
Mark Sleef5f2be42006-09-05 21:05:31 +000040 ~Impl() { stop(); }
Marc Slemkod466b212006-07-20 00:04:18 +000041
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000042 void start();
Marc Slemko0e53ccd2006-07-17 23:51:05 +000043
Marc Slemkod466b212006-07-20 00:04:18 +000044 void stop();
Marc Slemko0e53ccd2006-07-17 23:51:05 +000045
Mark Sleef5f2be42006-09-05 21:05:31 +000046 const ThreadManager::STATE state() const { return _state; }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000047
Marc Slemko6f038a72006-08-03 18:58:09 +000048 shared_ptr<ThreadFactory> threadFactory() const {
Marc Slemko0e53ccd2006-07-17 23:51:05 +000049 Synchronized s(_monitor);
Marc Slemko0e53ccd2006-07-17 23:51:05 +000050 return _threadFactory;
51 }
52
Mark Sleef5f2be42006-09-05 21:05:31 +000053 void threadFactory(shared_ptr<ThreadFactory> value) {
54 Synchronized s(_monitor);
Marc Slemko0e53ccd2006-07-17 23:51:05 +000055 _threadFactory = value;
56 }
57
Marc Slemkod466b212006-07-20 00:04:18 +000058 void addWorker(size_t value);
Marc Slemko0e53ccd2006-07-17 23:51:05 +000059
Marc Slemkod466b212006-07-20 00:04:18 +000060 void removeWorker(size_t value);
Marc Slemko0e53ccd2006-07-17 23:51:05 +000061
Mark Sleef5f2be42006-09-05 21:05:31 +000062 size_t idleWorkerCount() const { return _idleCount; }
Marc Slemko0e53ccd2006-07-17 23:51:05 +000063
64 size_t workerCount() const {
Marc Slemko0e53ccd2006-07-17 23:51:05 +000065 Synchronized s(_monitor);
Marc Slemkod466b212006-07-20 00:04:18 +000066 return _workerCount;
Marc Slemko0e53ccd2006-07-17 23:51:05 +000067 }
68
69 size_t pendingTaskCount() const {
Marc Slemko0e53ccd2006-07-17 23:51:05 +000070 Synchronized s(_monitor);
Marc Slemko0e53ccd2006-07-17 23:51:05 +000071 return _tasks.size();
72 }
73
74 size_t totalTaskCount() const {
Mark Sleef5f2be42006-09-05 21:05:31 +000075 Synchronized s(_monitor);
Marc Slemkod466b212006-07-20 00:04:18 +000076 return _tasks.size() + _workerCount - _idleCount;
Marc Slemko0e53ccd2006-07-17 23:51:05 +000077 }
78
Marc Slemko6f038a72006-08-03 18:58:09 +000079 void add(shared_ptr<Runnable> value);
Marc Slemko0e53ccd2006-07-17 23:51:05 +000080
Marc Slemko6f038a72006-08-03 18:58:09 +000081 void remove(shared_ptr<Runnable> task);
Marc Slemko0e53ccd2006-07-17 23:51:05 +000082
83private:
Marc Slemkod466b212006-07-20 00:04:18 +000084 size_t _workerCount;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000085 size_t _workerMaxCount;
Marc Slemko0e53ccd2006-07-17 23:51:05 +000086 size_t _idleCount;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000087 ThreadManager::STATE _state;
Marc Slemko6f038a72006-08-03 18:58:09 +000088 shared_ptr<ThreadFactory> _threadFactory;
Marc Slemko0e53ccd2006-07-17 23:51:05 +000089
Mark Sleef5f2be42006-09-05 21:05:31 +000090
Marc Slemko0e53ccd2006-07-17 23:51:05 +000091 friend class ThreadManager::Task;
Marc Slemko6f038a72006-08-03 18:58:09 +000092 std::queue<shared_ptr<Task> > _tasks;
Marc Slemko0e53ccd2006-07-17 23:51:05 +000093 Monitor _monitor;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000094 Monitor _workerMonitor;
95
Marc Slemko0e53ccd2006-07-17 23:51:05 +000096 friend class ThreadManager::Worker;
Marc Slemko6f038a72006-08-03 18:58:09 +000097 std::set<shared_ptr<Thread> > _workers;
Marc Slemko6f038a72006-08-03 18:58:09 +000098 std::set<shared_ptr<Thread> > _deadWorkers;
Marc Slemko0e53ccd2006-07-17 23:51:05 +000099};
Marc Slemko66949872006-07-15 01:52:39 +0000100
101class ThreadManager::Task : public Runnable {
102
Mark Sleef5f2be42006-09-05 21:05:31 +0000103 public:
Marc Slemko66949872006-07-15 01:52:39 +0000104 enum STATE {
105 WAITING,
106 EXECUTING,
107 CANCELLED,
108 COMPLETE
109 };
110
Marc Slemko6f038a72006-08-03 18:58:09 +0000111 Task(shared_ptr<Runnable> runnable) :
Marc Slemko66949872006-07-15 01:52:39 +0000112 _runnable(runnable),
Mark Sleef5f2be42006-09-05 21:05:31 +0000113 _state(WAITING) {}
Marc Slemko66949872006-07-15 01:52:39 +0000114
Mark Sleef5f2be42006-09-05 21:05:31 +0000115 ~Task() {}
Marc Slemko66949872006-07-15 01:52:39 +0000116
117 void run() {
Mark Sleef5f2be42006-09-05 21:05:31 +0000118 if (_state == EXECUTING) {
Marc Slemko66949872006-07-15 01:52:39 +0000119 _runnable->run();
120 _state = COMPLETE;
121 }
122 }
123
124 private:
Marc Slemko6f038a72006-08-03 18:58:09 +0000125 shared_ptr<Runnable> _runnable;
Marc Slemkod466b212006-07-20 00:04:18 +0000126 friend class ThreadManager::Worker;
Marc Slemko66949872006-07-15 01:52:39 +0000127 STATE _state;
128};
129
130class ThreadManager::Worker: public Runnable {
Marc Slemko66949872006-07-15 01:52:39 +0000131 enum STATE {
132 UNINITIALIZED,
133 STARTING,
134 STARTED,
135 STOPPING,
136 STOPPED
137 };
138
139 public:
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000140 Worker(ThreadManager::Impl* manager) :
Marc Slemko66949872006-07-15 01:52:39 +0000141 _manager(manager),
142 _state(UNINITIALIZED),
Mark Sleef5f2be42006-09-05 21:05:31 +0000143 _idle(false) {}
Marc Slemko66949872006-07-15 01:52:39 +0000144
145 ~Worker() {}
146
Mark Sleef5f2be42006-09-05 21:05:31 +0000147 bool isActive() const { return _manager->_workerCount <= _manager->_workerMaxCount; }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000148
Mark Sleef5f2be42006-09-05 21:05:31 +0000149 /**
150 * Worker entry point
151 *
152 * As long as worker thread is running, pull tasks off the task queue and
153 * execute.
154 */
Marc Slemko66949872006-07-15 01:52:39 +0000155 void run() {
Mark Sleef5f2be42006-09-05 21:05:31 +0000156 bool active = false;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000157 bool notifyManager = false;
158
Mark Sleef5f2be42006-09-05 21:05:31 +0000159 /**
160 * Increment worker semaphore and notify manager if worker count reached
161 * desired max
162 *
163 * Note: We have to release the monitor and acquire the workerMonitor
164 * since that is what the manager blocks on for worker add/remove
165 */
166 {
167 Synchronized s(_manager->_monitor);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000168 active = _manager->_workerCount < _manager->_workerMaxCount;
Mark Sleef5f2be42006-09-05 21:05:31 +0000169 if (active) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000170 _manager->_workerCount++;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000171 notifyManager = _manager->_workerCount == _manager->_workerMaxCount;
Marc Slemko66949872006-07-15 01:52:39 +0000172 }
173 }
174
Mark Sleef5f2be42006-09-05 21:05:31 +0000175 if (notifyManager) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000176 Synchronized s(_manager->_workerMonitor);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000177 _manager->_workerMonitor.notify();
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000178 notifyManager = false;
179 }
180
Mark Sleef5f2be42006-09-05 21:05:31 +0000181 while (active) {
Marc Slemko6f038a72006-08-03 18:58:09 +0000182 shared_ptr<ThreadManager::Task> task;
Marc Slemko66949872006-07-15 01:52:39 +0000183
Mark Sleef5f2be42006-09-05 21:05:31 +0000184 /**
185 * While holding manager monitor block for non-empty task queue (Also
186 * check that the thread hasn't been requested to stop). Once the queue
187 * is non-empty, dequeue a task, release monitor, and execute. If the
188 * worker max count has been decremented such that we exceed it, mark
189 * ourself inactive, decrement the worker count and notify the manager
190 * (technically we're notifying the next blocked thread but eventually
191 * the manager will see it.
192 */
193 {
194 Synchronized s(_manager->_monitor);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000195 active = isActive();
Mark Sleef5f2be42006-09-05 21:05:31 +0000196 while (active && _manager->_tasks.empty()) {
197 _manager->_idleCount++;
Marc Slemko66949872006-07-15 01:52:39 +0000198 _idle = true;
Mark Sleef5f2be42006-09-05 21:05:31 +0000199 _manager->_monitor.wait();
200 active = isActive();
Marc Slemko66949872006-07-15 01:52:39 +0000201 _idle = false;
Mark Sleef5f2be42006-09-05 21:05:31 +0000202 _manager->_idleCount--;
Marc Slemko66949872006-07-15 01:52:39 +0000203 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000204
Mark Sleef5f2be42006-09-05 21:05:31 +0000205 if (active) {
206 if (!_manager->_tasks.empty()) {
207 task = _manager->_tasks.front();
208 _manager->_tasks.pop();
209 if (task->_state == ThreadManager::Task::WAITING) {
210 task->_state = ThreadManager::Task::EXECUTING;
Marc Slemkod466b212006-07-20 00:04:18 +0000211 }
212 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000213 } else {
Mark Sleef5f2be42006-09-05 21:05:31 +0000214 _idle = true;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000215 _manager->_workerCount--;
Mark Sleef5f2be42006-09-05 21:05:31 +0000216 notifyManager = _manager->_workerCount == _manager->_workerMaxCount;
Marc Slemko66949872006-07-15 01:52:39 +0000217 }
218 }
Mark Sleef5f2be42006-09-05 21:05:31 +0000219
220 if (task != NULL) {
221 if (task->_state == ThreadManager::Task::EXECUTING) {
Marc Slemkod466b212006-07-20 00:04:18 +0000222 try {
Mark Sleef5f2be42006-09-05 21:05:31 +0000223 task->run();
224 } catch(...) {
225 // XXX need to log this
Marc Slemkod466b212006-07-20 00:04:18 +0000226 }
Marc Slemkod466b212006-07-20 00:04:18 +0000227 }
Marc Slemko66949872006-07-15 01:52:39 +0000228 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000229 }
Mark Sleef5f2be42006-09-05 21:05:31 +0000230
231 {
232 Synchronized s(_manager->_workerMonitor);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000233 _manager->_deadWorkers.insert(this->thread());
Mark Sleef5f2be42006-09-05 21:05:31 +0000234 if (notifyManager) {
235 _manager->_workerMonitor.notify();
Marc Slemko66949872006-07-15 01:52:39 +0000236 }
237 }
Mark Sleef5f2be42006-09-05 21:05:31 +0000238
Marc Slemko66949872006-07-15 01:52:39 +0000239 return;
240 }
Mark Sleef5f2be42006-09-05 21:05:31 +0000241
242 private:
243 ThreadManager::Impl* _manager;
244 friend class ThreadManager::Impl;
245 STATE _state;
246 bool _idle;
Marc Slemko66949872006-07-15 01:52:39 +0000247};
248
Mark Sleef5f2be42006-09-05 21:05:31 +0000249
250 void ThreadManager::Impl::addWorker(size_t value) {
Marc Slemko6f038a72006-08-03 18:58:09 +0000251 std::set<shared_ptr<Thread> > newThreads;
Mark Sleef5f2be42006-09-05 21:05:31 +0000252 for (size_t ix = 0; ix < value; ix++) {
253 class ThreadManager::Worker;
Marc Slemko6f038a72006-08-03 18:58:09 +0000254 shared_ptr<ThreadManager::Worker> worker = shared_ptr<ThreadManager::Worker>(new ThreadManager::Worker(this));
Marc Slemkod466b212006-07-20 00:04:18 +0000255 newThreads.insert(_threadFactory->newThread(worker));
Marc Slemko66949872006-07-15 01:52:39 +0000256 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000257
Mark Sleef5f2be42006-09-05 21:05:31 +0000258 {
259 Synchronized s(_monitor);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000260 _workerMaxCount+= value;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000261 _workers.insert(newThreads.begin(), newThreads.end());
262 }
Marc Slemko66949872006-07-15 01:52:39 +0000263
Mark Sleef5f2be42006-09-05 21:05:31 +0000264 for (std::set<shared_ptr<Thread> >::iterator ix = newThreads.begin(); ix != newThreads.end(); ix++) {
Marc Slemko6f038a72006-08-03 18:58:09 +0000265 shared_ptr<ThreadManager::Worker> worker = dynamic_pointer_cast<ThreadManager::Worker, Runnable>((*ix)->runnable());
Marc Slemkod466b212006-07-20 00:04:18 +0000266 worker->_state = ThreadManager::Worker::STARTING;
Marc Slemkod466b212006-07-20 00:04:18 +0000267 (*ix)->start();
268 }
269
Mark Sleef5f2be42006-09-05 21:05:31 +0000270 {
271 Synchronized s(_workerMonitor);
272 while (_workerCount != _workerMaxCount) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000273 _workerMonitor.wait();
274 }
275 }
276}
Marc Slemkod466b212006-07-20 00:04:18 +0000277
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000278void ThreadManager::Impl::start() {
279
Mark Sleef5f2be42006-09-05 21:05:31 +0000280 if (_state == ThreadManager::STOPPED) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000281 return;
282 }
283
Mark Sleef5f2be42006-09-05 21:05:31 +0000284 {
285 Synchronized s(_monitor);
286 if (_state == ThreadManager::UNINITIALIZED) {
287 if (_threadFactory == NULL) {
288 throw InvalidArgumentException();
289 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000290 _state = ThreadManager::STARTED;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000291 _monitor.notifyAll();
292 }
293
Mark Sleef5f2be42006-09-05 21:05:31 +0000294 while (_state == STARTING) {
Marc Slemkod466b212006-07-20 00:04:18 +0000295 _monitor.wait();
296 }
297 }
298}
299
300void ThreadManager::Impl::stop() {
Marc Slemkod466b212006-07-20 00:04:18 +0000301 bool doStop = false;
Mark Sleef5f2be42006-09-05 21:05:31 +0000302 if (_state == ThreadManager::STOPPED) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000303 return;
304 }
305
Mark Sleef5f2be42006-09-05 21:05:31 +0000306 {
307 Synchronized s(_monitor);
308 if (!_state != ThreadManager::STOPPING && _state != ThreadManager::STOPPED) {
Marc Slemkod466b212006-07-20 00:04:18 +0000309 doStop = true;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000310 _state = ThreadManager::STOPPING;
Marc Slemkod466b212006-07-20 00:04:18 +0000311 }
312 }
313
Mark Sleef5f2be42006-09-05 21:05:31 +0000314 if (doStop) {
Marc Slemkod466b212006-07-20 00:04:18 +0000315 removeWorker(_workerCount);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000316 _state = ThreadManager::STOPPING;
Marc Slemkod466b212006-07-20 00:04:18 +0000317 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000318
Marc Slemko6f038a72006-08-03 18:58:09 +0000319 // XXX
Mark Sleef5f2be42006-09-05 21:05:31 +0000320 // should be able to block here for transition to STOPPED since we're no
321 // using shared_ptrs
Marc Slemkod466b212006-07-20 00:04:18 +0000322}
323
324void ThreadManager::Impl::removeWorker(size_t value) {
Marc Slemko6f038a72006-08-03 18:58:09 +0000325 std::set<shared_ptr<Thread> > removedThreads;
Mark Sleef5f2be42006-09-05 21:05:31 +0000326 {
327 Synchronized s(_monitor);
328 if (value > _workerMaxCount) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000329 throw InvalidArgumentException();
330 }
331
332 _workerMaxCount-= value;
333
Mark Sleef5f2be42006-09-05 21:05:31 +0000334 if (_idleCount < value) {
335 for (size_t ix = 0; ix < _idleCount; ix++) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000336 _monitor.notify();
Marc Slemko66949872006-07-15 01:52:39 +0000337 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000338 } else {
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000339 _monitor.notifyAll();
Marc Slemko66949872006-07-15 01:52:39 +0000340 }
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000341 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000342
Mark Sleef5f2be42006-09-05 21:05:31 +0000343 {
344 Synchronized s(_workerMonitor);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000345
Mark Sleef5f2be42006-09-05 21:05:31 +0000346 while (_workerCount != _workerMaxCount) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000347 _workerMonitor.wait();
348 }
349
Mark Sleef5f2be42006-09-05 21:05:31 +0000350 for (std::set<shared_ptr<Thread> >::iterator ix = _deadWorkers.begin(); ix != _deadWorkers.end(); ix++) {
351 _workers.erase(*ix);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000352 }
Mark Sleef5f2be42006-09-05 21:05:31 +0000353
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000354 _deadWorkers.clear();
355 }
356}
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000357
Marc Slemko6f038a72006-08-03 18:58:09 +0000358void ThreadManager::Impl::add(shared_ptr<Runnable> value) {
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000359 Synchronized s(_monitor);
360
Mark Sleef5f2be42006-09-05 21:05:31 +0000361 if (_state != ThreadManager::STARTED) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000362 throw IllegalStateException();
363 }
Marc Slemkod466b212006-07-20 00:04:18 +0000364
Marc Slemko6f038a72006-08-03 18:58:09 +0000365 _tasks.push(shared_ptr<ThreadManager::Task>(new ThreadManager::Task(value)));
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000366
Mark Sleef5f2be42006-09-05 21:05:31 +0000367 // If idle thread is available notify it, otherwise all worker threads are
368 // running and will get around to this task in time.
369 if (_idleCount > 0) {
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000370 _monitor.notify();
371 }
Marc Slemko66949872006-07-15 01:52:39 +0000372 }
373
Marc Slemko6f038a72006-08-03 18:58:09 +0000374void ThreadManager::Impl::remove(shared_ptr<Runnable> task) {
Mark Sleef5f2be42006-09-05 21:05:31 +0000375 Synchronized s(_monitor);
376 if (_state != ThreadManager::STARTED) {
377 throw IllegalStateException();
378 }
Marc Slemko66949872006-07-15 01:52:39 +0000379}
380
Marc Slemkod466b212006-07-20 00:04:18 +0000381class SimpleThreadManager : public ThreadManager::Impl {
Marc Slemko66949872006-07-15 01:52:39 +0000382
Marc Slemkod466b212006-07-20 00:04:18 +0000383public:
Marc Slemkod466b212006-07-20 00:04:18 +0000384 SimpleThreadManager(size_t workerCount=4) :
385 _workerCount(workerCount),
386 _firstTime(true) {
387 }
Marc Slemko66949872006-07-15 01:52:39 +0000388
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000389 void start() {
390 ThreadManager::Impl::start();
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000391 addWorker(_workerCount);
Marc Slemkod466b212006-07-20 00:04:18 +0000392 }
393
394private:
Marc Slemkod466b212006-07-20 00:04:18 +0000395 const size_t _workerCount;
396 bool _firstTime;
397 Monitor _monitor;
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000398};
Marc Slemko66949872006-07-15 01:52:39 +0000399
Marc Slemko66949872006-07-15 01:52:39 +0000400
Marc Slemko6f038a72006-08-03 18:58:09 +0000401shared_ptr<ThreadManager> ThreadManager::newThreadManager() {
402 return shared_ptr<ThreadManager>(new ThreadManager::Impl());
Marc Slemkod466b212006-07-20 00:04:18 +0000403}
Marc Slemko66949872006-07-15 01:52:39 +0000404
Marc Slemko6f038a72006-08-03 18:58:09 +0000405shared_ptr<ThreadManager> ThreadManager::newSimpleThreadManager(size_t count) {
406 return shared_ptr<ThreadManager>(new SimpleThreadManager(count));
Marc Slemkod466b212006-07-20 00:04:18 +0000407}
Marc Slemko66949872006-07-15 01:52:39 +0000408
409}}} // facebook::thrift::concurrency