blob: 895d1cda5351ff40a456a80eb9bd75937b0b9a5a [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() :
Mark Slee2f6404d2006-10-10 01:37:40 +000035 workerCount_(0),
36 workerMaxCount_(0),
37 idleCount_(0),
38 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 Slee2f6404d2006-10-10 01:37:40 +000046 const ThreadManager::STATE state() const {
47 return state_;
48 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000049
Marc Slemko6f038a72006-08-03 18:58:09 +000050 shared_ptr<ThreadFactory> threadFactory() const {
Mark Slee2f6404d2006-10-10 01:37:40 +000051 Synchronized s(monitor_);
52 return threadFactory_;
Marc Slemko0e53ccd2006-07-17 23:51:05 +000053 }
54
Mark Sleef5f2be42006-09-05 21:05:31 +000055 void threadFactory(shared_ptr<ThreadFactory> value) {
Mark Slee2f6404d2006-10-10 01:37:40 +000056 Synchronized s(monitor_);
57 threadFactory_ = value;
Marc Slemko0e53ccd2006-07-17 23:51:05 +000058 }
59
Marc Slemkod466b212006-07-20 00:04:18 +000060 void addWorker(size_t value);
Marc Slemko0e53ccd2006-07-17 23:51:05 +000061
Marc Slemkod466b212006-07-20 00:04:18 +000062 void removeWorker(size_t value);
Marc Slemko0e53ccd2006-07-17 23:51:05 +000063
Mark Slee2f6404d2006-10-10 01:37:40 +000064 size_t idleWorkerCount() const {
65 return idleCount_;
66 }
Marc Slemko0e53ccd2006-07-17 23:51:05 +000067
68 size_t workerCount() const {
Mark Slee2f6404d2006-10-10 01:37:40 +000069 Synchronized s(monitor_);
70 return workerCount_;
Marc Slemko0e53ccd2006-07-17 23:51:05 +000071 }
72
73 size_t pendingTaskCount() const {
Mark Slee2f6404d2006-10-10 01:37:40 +000074 Synchronized s(monitor_);
75 return tasks_.size();
Marc Slemko0e53ccd2006-07-17 23:51:05 +000076 }
77
78 size_t totalTaskCount() const {
Mark Slee2f6404d2006-10-10 01:37:40 +000079 Synchronized s(monitor_);
80 return tasks_.size() + workerCount_ - idleCount_;
Marc Slemko0e53ccd2006-07-17 23:51:05 +000081 }
82
Marc Slemko6f038a72006-08-03 18:58:09 +000083 void add(shared_ptr<Runnable> value);
Marc Slemko0e53ccd2006-07-17 23:51:05 +000084
Marc Slemko6f038a72006-08-03 18:58:09 +000085 void remove(shared_ptr<Runnable> task);
Marc Slemko0e53ccd2006-07-17 23:51:05 +000086
87private:
Mark Slee2f6404d2006-10-10 01:37:40 +000088 size_t workerCount_;
89 size_t workerMaxCount_;
90 size_t idleCount_;
91 ThreadManager::STATE state_;
92 shared_ptr<ThreadFactory> threadFactory_;
Marc Slemko0e53ccd2006-07-17 23:51:05 +000093
Mark Sleef5f2be42006-09-05 21:05:31 +000094
Marc Slemko0e53ccd2006-07-17 23:51:05 +000095 friend class ThreadManager::Task;
Mark Slee2f6404d2006-10-10 01:37:40 +000096 std::queue<shared_ptr<Task> > tasks_;
97 Monitor monitor_;
98 Monitor workerMonitor_;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +000099
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000100 friend class ThreadManager::Worker;
Mark Slee2f6404d2006-10-10 01:37:40 +0000101 std::set<shared_ptr<Thread> > workers_;
102 std::set<shared_ptr<Thread> > deadWorkers_;
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000103};
Marc Slemko66949872006-07-15 01:52:39 +0000104
105class ThreadManager::Task : public Runnable {
106
Mark Sleef5f2be42006-09-05 21:05:31 +0000107 public:
Marc Slemko66949872006-07-15 01:52:39 +0000108 enum STATE {
109 WAITING,
110 EXECUTING,
111 CANCELLED,
112 COMPLETE
113 };
114
Marc Slemko6f038a72006-08-03 18:58:09 +0000115 Task(shared_ptr<Runnable> runnable) :
Mark Slee2f6404d2006-10-10 01:37:40 +0000116 runnable_(runnable),
117 state_(WAITING) {}
Marc Slemko66949872006-07-15 01:52:39 +0000118
Mark Sleef5f2be42006-09-05 21:05:31 +0000119 ~Task() {}
Marc Slemko66949872006-07-15 01:52:39 +0000120
121 void run() {
Mark Slee2f6404d2006-10-10 01:37:40 +0000122 if (state_ == EXECUTING) {
123 runnable_->run();
124 state_ = COMPLETE;
Marc Slemko66949872006-07-15 01:52:39 +0000125 }
126 }
127
128 private:
Mark Slee2f6404d2006-10-10 01:37:40 +0000129 shared_ptr<Runnable> runnable_;
Marc Slemkod466b212006-07-20 00:04:18 +0000130 friend class ThreadManager::Worker;
Mark Slee2f6404d2006-10-10 01:37:40 +0000131 STATE state_;
Marc Slemko66949872006-07-15 01:52:39 +0000132};
133
134class ThreadManager::Worker: public Runnable {
Marc Slemko66949872006-07-15 01:52:39 +0000135 enum STATE {
136 UNINITIALIZED,
137 STARTING,
138 STARTED,
139 STOPPING,
140 STOPPED
141 };
142
143 public:
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000144 Worker(ThreadManager::Impl* manager) :
Mark Slee2f6404d2006-10-10 01:37:40 +0000145 manager_(manager),
146 state_(UNINITIALIZED),
147 idle_(false) {}
Marc Slemko66949872006-07-15 01:52:39 +0000148
149 ~Worker() {}
150
Mark Slee2f6404d2006-10-10 01:37:40 +0000151 bool isActive() const {
152 return manager_->workerCount_ <= manager_->workerMaxCount_;
153 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000154
Mark Sleef5f2be42006-09-05 21:05:31 +0000155 /**
156 * Worker entry point
157 *
158 * As long as worker thread is running, pull tasks off the task queue and
159 * execute.
160 */
Marc Slemko66949872006-07-15 01:52:39 +0000161 void run() {
Mark Sleef5f2be42006-09-05 21:05:31 +0000162 bool active = false;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000163 bool notifyManager = false;
164
Mark Sleef5f2be42006-09-05 21:05:31 +0000165 /**
166 * Increment worker semaphore and notify manager if worker count reached
167 * desired max
168 *
169 * Note: We have to release the monitor and acquire the workerMonitor
170 * since that is what the manager blocks on for worker add/remove
171 */
172 {
Mark Slee2f6404d2006-10-10 01:37:40 +0000173 Synchronized s(manager_->monitor_);
174 active = manager_->workerCount_ < manager_->workerMaxCount_;
Mark Sleef5f2be42006-09-05 21:05:31 +0000175 if (active) {
Mark Slee2f6404d2006-10-10 01:37:40 +0000176 manager_->workerCount_++;
177 notifyManager = manager_->workerCount_ == manager_->workerMaxCount_;
Marc Slemko66949872006-07-15 01:52:39 +0000178 }
179 }
180
Mark Sleef5f2be42006-09-05 21:05:31 +0000181 if (notifyManager) {
Mark Slee2f6404d2006-10-10 01:37:40 +0000182 Synchronized s(manager_->workerMonitor_);
183 manager_->workerMonitor_.notify();
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000184 notifyManager = false;
185 }
186
Mark Sleef5f2be42006-09-05 21:05:31 +0000187 while (active) {
Marc Slemko6f038a72006-08-03 18:58:09 +0000188 shared_ptr<ThreadManager::Task> task;
Marc Slemko66949872006-07-15 01:52:39 +0000189
Mark Sleef5f2be42006-09-05 21:05:31 +0000190 /**
191 * While holding manager monitor block for non-empty task queue (Also
192 * check that the thread hasn't been requested to stop). Once the queue
193 * is non-empty, dequeue a task, release monitor, and execute. If the
194 * worker max count has been decremented such that we exceed it, mark
195 * ourself inactive, decrement the worker count and notify the manager
196 * (technically we're notifying the next blocked thread but eventually
197 * the manager will see it.
198 */
199 {
Mark Slee2f6404d2006-10-10 01:37:40 +0000200 Synchronized s(manager_->monitor_);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000201 active = isActive();
Mark Slee2f6404d2006-10-10 01:37:40 +0000202 while (active && manager_->tasks_.empty()) {
203 manager_->idleCount_++;
204 idle_ = true;
205 manager_->monitor_.wait();
Mark Sleef5f2be42006-09-05 21:05:31 +0000206 active = isActive();
Mark Slee2f6404d2006-10-10 01:37:40 +0000207 idle_ = false;
208 manager_->idleCount_--;
Marc Slemko66949872006-07-15 01:52:39 +0000209 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000210
Mark Sleef5f2be42006-09-05 21:05:31 +0000211 if (active) {
Mark Slee2f6404d2006-10-10 01:37:40 +0000212 if (!manager_->tasks_.empty()) {
213 task = manager_->tasks_.front();
214 manager_->tasks_.pop();
215 if (task->state_ == ThreadManager::Task::WAITING) {
216 task->state_ = ThreadManager::Task::EXECUTING;
Marc Slemkod466b212006-07-20 00:04:18 +0000217 }
218 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000219 } else {
Mark Slee2f6404d2006-10-10 01:37:40 +0000220 idle_ = true;
221 manager_->workerCount_--;
222 notifyManager = manager_->workerCount_ == manager_->workerMaxCount_;
Marc Slemko66949872006-07-15 01:52:39 +0000223 }
224 }
Mark Sleef5f2be42006-09-05 21:05:31 +0000225
226 if (task != NULL) {
Mark Slee2f6404d2006-10-10 01:37:40 +0000227 if (task->state_ == ThreadManager::Task::EXECUTING) {
Marc Slemkod466b212006-07-20 00:04:18 +0000228 try {
Mark Sleef5f2be42006-09-05 21:05:31 +0000229 task->run();
230 } catch(...) {
231 // XXX need to log this
Marc Slemkod466b212006-07-20 00:04:18 +0000232 }
Marc Slemkod466b212006-07-20 00:04:18 +0000233 }
Marc Slemko66949872006-07-15 01:52:39 +0000234 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000235 }
Mark Sleef5f2be42006-09-05 21:05:31 +0000236
237 {
Mark Slee2f6404d2006-10-10 01:37:40 +0000238 Synchronized s(manager_->workerMonitor_);
239 manager_->deadWorkers_.insert(this->thread());
Mark Sleef5f2be42006-09-05 21:05:31 +0000240 if (notifyManager) {
Mark Slee2f6404d2006-10-10 01:37:40 +0000241 manager_->workerMonitor_.notify();
Marc Slemko66949872006-07-15 01:52:39 +0000242 }
243 }
Mark Sleef5f2be42006-09-05 21:05:31 +0000244
Marc Slemko66949872006-07-15 01:52:39 +0000245 return;
246 }
Mark Sleef5f2be42006-09-05 21:05:31 +0000247
248 private:
Mark Slee2f6404d2006-10-10 01:37:40 +0000249 ThreadManager::Impl* manager_;
Mark Sleef5f2be42006-09-05 21:05:31 +0000250 friend class ThreadManager::Impl;
Mark Slee2f6404d2006-10-10 01:37:40 +0000251 STATE state_;
252 bool idle_;
Marc Slemko66949872006-07-15 01:52:39 +0000253};
254
Mark Sleef5f2be42006-09-05 21:05:31 +0000255
256 void ThreadManager::Impl::addWorker(size_t value) {
Marc Slemko6f038a72006-08-03 18:58:09 +0000257 std::set<shared_ptr<Thread> > newThreads;
Mark Sleef5f2be42006-09-05 21:05:31 +0000258 for (size_t ix = 0; ix < value; ix++) {
259 class ThreadManager::Worker;
Marc Slemko6f038a72006-08-03 18:58:09 +0000260 shared_ptr<ThreadManager::Worker> worker = shared_ptr<ThreadManager::Worker>(new ThreadManager::Worker(this));
Mark Slee2f6404d2006-10-10 01:37:40 +0000261 newThreads.insert(threadFactory_->newThread(worker));
Marc Slemko66949872006-07-15 01:52:39 +0000262 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000263
Mark Sleef5f2be42006-09-05 21:05:31 +0000264 {
Mark Slee2f6404d2006-10-10 01:37:40 +0000265 Synchronized s(monitor_);
266 workerMaxCount_ += value;
267 workers_.insert(newThreads.begin(), newThreads.end());
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000268 }
Marc Slemko66949872006-07-15 01:52:39 +0000269
Mark Sleef5f2be42006-09-05 21:05:31 +0000270 for (std::set<shared_ptr<Thread> >::iterator ix = newThreads.begin(); ix != newThreads.end(); ix++) {
Marc Slemko6f038a72006-08-03 18:58:09 +0000271 shared_ptr<ThreadManager::Worker> worker = dynamic_pointer_cast<ThreadManager::Worker, Runnable>((*ix)->runnable());
Mark Slee2f6404d2006-10-10 01:37:40 +0000272 worker->state_ = ThreadManager::Worker::STARTING;
Marc Slemkod466b212006-07-20 00:04:18 +0000273 (*ix)->start();
274 }
275
Mark Sleef5f2be42006-09-05 21:05:31 +0000276 {
Mark Slee2f6404d2006-10-10 01:37:40 +0000277 Synchronized s(workerMonitor_);
278 while (workerCount_ != workerMaxCount_) {
279 workerMonitor_.wait();
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000280 }
281 }
282}
Marc Slemkod466b212006-07-20 00:04:18 +0000283
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000284void ThreadManager::Impl::start() {
285
Mark Slee2f6404d2006-10-10 01:37:40 +0000286 if (state_ == ThreadManager::STOPPED) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000287 return;
288 }
289
Mark Sleef5f2be42006-09-05 21:05:31 +0000290 {
Mark Slee2f6404d2006-10-10 01:37:40 +0000291 Synchronized s(monitor_);
292 if (state_ == ThreadManager::UNINITIALIZED) {
293 if (threadFactory_ == NULL) {
Mark Sleef5f2be42006-09-05 21:05:31 +0000294 throw InvalidArgumentException();
295 }
Mark Slee2f6404d2006-10-10 01:37:40 +0000296 state_ = ThreadManager::STARTED;
297 monitor_.notifyAll();
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000298 }
299
Mark Slee2f6404d2006-10-10 01:37:40 +0000300 while (state_ == STARTING) {
301 monitor_.wait();
Marc Slemkod466b212006-07-20 00:04:18 +0000302 }
303 }
304}
305
306void ThreadManager::Impl::stop() {
Marc Slemkod466b212006-07-20 00:04:18 +0000307 bool doStop = false;
Mark Slee2f6404d2006-10-10 01:37:40 +0000308 if (state_ == ThreadManager::STOPPED) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000309 return;
310 }
311
Mark Sleef5f2be42006-09-05 21:05:31 +0000312 {
Mark Slee2f6404d2006-10-10 01:37:40 +0000313 Synchronized s(monitor_);
314 if (!state_ != ThreadManager::STOPPING && state_ != ThreadManager::STOPPED) {
Marc Slemkod466b212006-07-20 00:04:18 +0000315 doStop = true;
Mark Slee2f6404d2006-10-10 01:37:40 +0000316 state_ = ThreadManager::STOPPING;
Marc Slemkod466b212006-07-20 00:04:18 +0000317 }
318 }
319
Mark Sleef5f2be42006-09-05 21:05:31 +0000320 if (doStop) {
Mark Slee2f6404d2006-10-10 01:37:40 +0000321 removeWorker(workerCount_);
322 state_ = ThreadManager::STOPPING;
Marc Slemkod466b212006-07-20 00:04:18 +0000323 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000324
Marc Slemko6f038a72006-08-03 18:58:09 +0000325 // XXX
Mark Sleef5f2be42006-09-05 21:05:31 +0000326 // should be able to block here for transition to STOPPED since we're no
327 // using shared_ptrs
Marc Slemkod466b212006-07-20 00:04:18 +0000328}
329
330void ThreadManager::Impl::removeWorker(size_t value) {
Marc Slemko6f038a72006-08-03 18:58:09 +0000331 std::set<shared_ptr<Thread> > removedThreads;
Mark Sleef5f2be42006-09-05 21:05:31 +0000332 {
Mark Slee2f6404d2006-10-10 01:37:40 +0000333 Synchronized s(monitor_);
334 if (value > workerMaxCount_) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000335 throw InvalidArgumentException();
336 }
337
Mark Slee2f6404d2006-10-10 01:37:40 +0000338 workerMaxCount_ -= value;
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000339
Mark Slee2f6404d2006-10-10 01:37:40 +0000340 if (idleCount_ < value) {
341 for (size_t ix = 0; ix < idleCount_; ix++) {
342 monitor_.notify();
Marc Slemko66949872006-07-15 01:52:39 +0000343 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000344 } else {
Mark Slee2f6404d2006-10-10 01:37:40 +0000345 monitor_.notifyAll();
Marc Slemko66949872006-07-15 01:52:39 +0000346 }
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000347 }
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000348
Mark Sleef5f2be42006-09-05 21:05:31 +0000349 {
Mark Slee2f6404d2006-10-10 01:37:40 +0000350 Synchronized s(workerMonitor_);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000351
Mark Slee2f6404d2006-10-10 01:37:40 +0000352 while (workerCount_ != workerMaxCount_) {
353 workerMonitor_.wait();
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000354 }
355
Mark Slee2f6404d2006-10-10 01:37:40 +0000356 for (std::set<shared_ptr<Thread> >::iterator ix = deadWorkers_.begin(); ix != deadWorkers_.end(); ix++) {
357 workers_.erase(*ix);
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000358 }
Mark Sleef5f2be42006-09-05 21:05:31 +0000359
Mark Slee2f6404d2006-10-10 01:37:40 +0000360 deadWorkers_.clear();
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000361 }
362}
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000363
Marc Slemko6f038a72006-08-03 18:58:09 +0000364void ThreadManager::Impl::add(shared_ptr<Runnable> value) {
Mark Slee2f6404d2006-10-10 01:37:40 +0000365 Synchronized s(monitor_);
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000366
Mark Slee2f6404d2006-10-10 01:37:40 +0000367 if (state_ != ThreadManager::STARTED) {
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000368 throw IllegalStateException();
369 }
Marc Slemkod466b212006-07-20 00:04:18 +0000370
Mark Slee2f6404d2006-10-10 01:37:40 +0000371 tasks_.push(shared_ptr<ThreadManager::Task>(new ThreadManager::Task(value)));
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000372
Mark Sleef5f2be42006-09-05 21:05:31 +0000373 // If idle thread is available notify it, otherwise all worker threads are
374 // running and will get around to this task in time.
Mark Slee2f6404d2006-10-10 01:37:40 +0000375 if (idleCount_ > 0) {
376 monitor_.notify();
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000377 }
Marc Slemko66949872006-07-15 01:52:39 +0000378 }
379
Marc Slemko6f038a72006-08-03 18:58:09 +0000380void ThreadManager::Impl::remove(shared_ptr<Runnable> task) {
Mark Slee2f6404d2006-10-10 01:37:40 +0000381 Synchronized s(monitor_);
382 if (state_ != ThreadManager::STARTED) {
Mark Sleef5f2be42006-09-05 21:05:31 +0000383 throw IllegalStateException();
384 }
Marc Slemko66949872006-07-15 01:52:39 +0000385}
386
Marc Slemkod466b212006-07-20 00:04:18 +0000387class SimpleThreadManager : public ThreadManager::Impl {
Marc Slemko66949872006-07-15 01:52:39 +0000388
Marc Slemkod466b212006-07-20 00:04:18 +0000389public:
Marc Slemkod466b212006-07-20 00:04:18 +0000390 SimpleThreadManager(size_t workerCount=4) :
Mark Slee2f6404d2006-10-10 01:37:40 +0000391 workerCount_(workerCount),
392 firstTime_(true) {
Marc Slemkod466b212006-07-20 00:04:18 +0000393 }
Marc Slemko66949872006-07-15 01:52:39 +0000394
Marc Slemkofe5ba12e2006-07-20 21:16:27 +0000395 void start() {
396 ThreadManager::Impl::start();
Mark Slee2f6404d2006-10-10 01:37:40 +0000397 addWorker(workerCount_);
Marc Slemkod466b212006-07-20 00:04:18 +0000398 }
399
400private:
Mark Slee2f6404d2006-10-10 01:37:40 +0000401 const size_t workerCount_;
402 bool firstTime_;
403 Monitor monitor_;
Marc Slemko0e53ccd2006-07-17 23:51:05 +0000404};
Marc Slemko66949872006-07-15 01:52:39 +0000405
Marc Slemko66949872006-07-15 01:52:39 +0000406
Marc Slemko6f038a72006-08-03 18:58:09 +0000407shared_ptr<ThreadManager> ThreadManager::newThreadManager() {
408 return shared_ptr<ThreadManager>(new ThreadManager::Impl());
Marc Slemkod466b212006-07-20 00:04:18 +0000409}
Marc Slemko66949872006-07-15 01:52:39 +0000410
Marc Slemko6f038a72006-08-03 18:58:09 +0000411shared_ptr<ThreadManager> ThreadManager::newSimpleThreadManager(size_t count) {
412 return shared_ptr<ThreadManager>(new SimpleThreadManager(count));
Marc Slemkod466b212006-07-20 00:04:18 +0000413}
Marc Slemko66949872006-07-15 01:52:39 +0000414
415}}} // facebook::thrift::concurrency