16muduo_base库源码分析(七)

来源:互联网 发布:蒙泰5.0软件官方下载 编辑:程序博客网 时间:2024/06/05 06:34

1.ThreadPool类图


2.代码

(1)线程池的数据是固定的
(2)无界缓冲区queue
ThreadPool.h
// Use of this source code is governed by a BSD-style license// that can be found in the License file.//// Author: Shuo Chen (chenshuo at chenshuo dot com)#ifndef MUDUO_BASE_THREADPOOL_H#define MUDUO_BASE_THREADPOOL_H#include <muduo/base/Condition.h>#include <muduo/base/Mutex.h>#include <muduo/base/Thread.h>#include <muduo/base/Types.h>#include <boost/function.hpp>#include <boost/noncopyable.hpp>#include <boost/ptr_container/ptr_vector.hpp>#include <deque>namespace muduo{class ThreadPool : boost::noncopyable{ public:  typedef boost::function<void ()> Task;  explicit ThreadPool(const string& name = string());  ~ThreadPool();  void start(int numThreads);  void stop();  void run(const Task& f); private:  void runInThread();  Task take();  MutexLock mutex_;  Condition cond_;  string name_;  boost::ptr_vector<muduo::Thread> threads_;  std::deque<Task> queue_;  bool running_;};}#endif
ThreadPool.cc
// Use of this source code is governed by a BSD-style license// that can be found in the License file.//// Author: Shuo Chen (chenshuo at chenshuo dot com)#include <muduo/base/ThreadPool.h>#include <muduo/base/Exception.h>#include <boost/bind.hpp>#include <assert.h>#include <stdio.h>using namespace muduo;ThreadPool::ThreadPool(const string& name)  : mutex_(),    cond_(mutex_),    name_(name),    running_(false){}ThreadPool::~ThreadPool(){  if (running_)  {    stop();  }}void ThreadPool::start(int numThreads){  assert(threads_.empty());  running_ = true;  threads_.reserve(numThreads);  for (int i = 0; i < numThreads; ++i)  {    char id[32];    snprintf(id, sizeof id, "%d", i);    threads_.push_back(new muduo::Thread(          boost::bind(&ThreadPool::runInThread, this), name_+id));    threads_[i].start();  }}void ThreadPool::stop(){  {  MutexLockGuard lock(mutex_);  running_ = false;  cond_.notifyAll();  }  for_each(threads_.begin(),           threads_.end(),           boost::bind(&muduo::Thread::join, _1));}void ThreadPool::run(const Task& task){  if (threads_.empty())  {    task();  }  else  {    MutexLockGuard lock(mutex_);    queue_.push_back(task);    cond_.notify();  }}ThreadPool::Task ThreadPool::take(){  MutexLockGuard lock(mutex_);  // always use a while-loop, due to spurious wakeup  while (queue_.empty() && running_)  {    cond_.wait();  }  Task task;  if(!queue_.empty())  {    task = queue_.front();    queue_.pop_front();  }  return task;}void ThreadPool::runInThread(){  try  {    while (running_)    {      Task task(take());      if (task)      {        task();      }    }  }  catch (const Exception& ex)  {    fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());    fprintf(stderr, "reason: %s\n", ex.what());    fprintf(stderr, "stack trace: %s\n", ex.stackTrace());    abort();  }  catch (const std::exception& ex)  {    fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());    fprintf(stderr, "reason: %s\n", ex.what());    abort();  }  catch (...)  {    fprintf(stderr, "unknown exception caught in ThreadPool %s\n", name_.c_str());    throw; // rethrow  }}
ThreadPool_test.cc
#include <muduo/base/ThreadPool.h>#include <muduo/base/CountDownLatch.h>#include <muduo/base/CurrentThread.h>#include <boost/bind.hpp>#include <stdio.h>void print(){  printf("tid=%d\n", muduo::CurrentThread::tid());}void printString(const std::string& str){  printf("tid=%d, str=%s\n", muduo::CurrentThread::tid(), str.c_str());}int main(){  muduo::ThreadPool pool("MainThreadPool");  pool.start(5);  pool.run(print);  pool.run(print);  for (int i = 0; i < 100; ++i)  {    char buf[32];    snprintf(buf, sizeof buf, "task %d", i);    pool.run(boost::bind(printString, std::string(buf)));  }  muduo::CountDownLatch latch(1);  pool.run(boost::bind(&muduo::CountDownLatch::countDown, &latch));  latch.wait();  pool.stop();}