1// excerpts from http://code.google.com/p/muduo/
2//
3// Use of this source code is governed by a BSD-style license
4// that can be found in the License file.
5//
6// Author: Shuo Chen (giantchen at gmail dot com)
7
8#include "ThreadPool.h"
9#include "Exception.h"
10
11#include <boost/bind.hpp>
12#include <assert.h>
13#include <stdio.h>
14
15using namespace muduo;
16
17ThreadPool::ThreadPool(const std::string& name)
18  : mutex_(),
19    cond_(mutex_),
20    name_(name),
21    running_(false)
22{
23}
24
25ThreadPool::~ThreadPool()
26{
27  if (running_)
28  {
29    stop();
30  }
31}
32
33void ThreadPool::start(int numThreads)
34{
35  assert(threads_.empty());
36  running_ = true;
37  threads_.reserve(numThreads);
38  for (int i = 0; i < numThreads; ++i)
39  {
40    char id[32];
41    snprintf(id, sizeof id, "%d", i);
42    threads_.push_back(new muduo::Thread(
43          boost::bind(&ThreadPool::runInThread, this), name_+id));
44    threads_[i].start();
45  }
46}
47
48void ThreadPool::stop()
49{
50  running_ = false;
51  cond_.notifyAll();
52  for_each(threads_.begin(),
53           threads_.end(),
54           boost::bind(&muduo::Thread::join, _1));
55}
56
57void ThreadPool::run(const Task& task)
58{
59  if (threads_.empty())
60  {
61    task();
62  }
63  else
64  {
65    MutexLockGuard lock(mutex_);
66    queue_.push_back(task);
67    cond_.notify();
68  }
69}
70
71ThreadPool::Task ThreadPool::take()
72{
73  MutexLockGuard lock(mutex_);
74  while (queue_.empty() && running_)
75  {
76    cond_.wait();
77  }
78  Task task;
79  if(!queue_.empty())
80  {
81    task = queue_.front();
82    queue_.pop_front();
83  }
84  return task;
85}
86
87void ThreadPool::runInThread()
88{
89  try
90  {
91    while (running_)
92    {
93      Task task(take());
94      if (task)
95      {
96        task();
97      }
98    }
99  }
100  catch (const Exception& ex)
101  {
102    fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());
103    fprintf(stderr, "reason: %s\n", ex.what());
104    fprintf(stderr, "stack trace: %s\n", ex.stackTrace());
105    abort();
106  }
107  catch (const std::exception& ex)
108  {
109    fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());
110    fprintf(stderr, "reason: %s\n", ex.what());
111    abort();
112  }
113  catch (...)
114  {
115    fprintf(stderr, "unknown exception caught in ThreadPool %s\n", name_.c_str());
116    abort();
117  }
118}
119
120