DelegateSimpleThreadPool

来源:互联网 发布:杂志 知乎 编辑:程序博客网 时间:2024/06/06 12:23

class DelegateSimpleThreadPool : public DelegateSimpleThread::Delegate {

 public:

  typedef DelegateSimpleThread::Delegate Delegate;

 

  DelegateSimpleThreadPool(const std::string name_prefix, int num_threads)

      : name_prefix_(name_prefix), num_threads_(num_threads),

        dry_(true, false) { }

  ~DelegateSimpleThreadPool();

 

  // Start up all of the underlying threads, and start processing work if we

  // have any.

  void Start();

 

  // Make sure all outstanding work is finished, and wait for and destroy all

  // of the underlying threads in the pool.

  void JoinAll();

 

  // It is safe to AddWork() any time, before or after Start().

  // Delegate* should always be a valid pointer, NULL is reserved internally.

  void AddWork(Delegate* work, int repeat_count);

  void AddWork(Delegate* work) {

    AddWork(work, 1);

  }

 

  // We implement the Delegate interface, for running our internal threads.

  virtual void Run();

 

 private:

  const std::string name_prefix_;

  int num_threads_;

  std::vector<DelegateSimpleThread*> threads_;

  std::queue<Delegate*> delegates_;

  Lock lock_;            // Locks delegates_

  WaitableEvent dry_;    // Not signaled when there is no work to do.

};

DelegateSimpleThreadPool::~DelegateSimpleThreadPool() {
  DCHECK(threads_.empty());
  DCHECK(delegates_.empty());
  DCHECK(!dry_.IsSignaled());
}
void DelegateSimpleThreadPool::Start() {
  DCHECK(threads_.empty()) << "Start() called with outstanding threads.";
  for (int i = 0; i < num_threads_; ++i) {
    DelegateSimpleThread* thread = new DelegateSimpleThread(this, name_prefix_);
    thread->Start();
    threads_.push_back(thread);
  }
}
void DelegateSimpleThreadPool::JoinAll() {
  DCHECK(!threads_.empty()) << "JoinAll() called with no outstanding threads.";
  // Tell all our threads to quit their worker loop.
  AddWork(NULL, num_threads_);
  // Join and destroy all the worker threads.
  for (int i = 0; i < num_threads_; ++i) {
    threads_[i]->Join();
    delete threads_[i];
  }
  threads_.clear();
  DCHECK(delegates_.empty());
}
void DelegateSimpleThreadPool::AddWork(Delegate* delegate, int repeat_count) {
  AutoLock locked(lock_);
  for (int i = 0; i < repeat_count; ++i)
    delegates_.push(delegate);
  // If we were empty, signal that we have work now.
  if (!dry_.IsSignaled())
    dry_.Signal();
}
void DelegateSimpleThreadPool::Run() {
  Delegate* work;
  while (true) {
    dry_.Wait();
    {
      AutoLock locked(lock_);
      if (!dry_.IsSignaled())
        continue;
      DCHECK(!delegates_.empty());
      work = delegates_.front();
      delegates_.pop();
      // Signal to any other threads that we're currently out of work.
      if (delegates_.empty())
        dry_.Reset();
    }
    // A NULL delegate pointer signals us to quit.
    if (!work)
      break;
    work->Run();
  }
}