muduo库的BlockingQueue和BoundBlockingQueue类剖析

9 篇文章 1 订阅

转载:http://blog.csdn.net/freeelinux/article/details/53428629

一:无界阻塞队列


muduo库的BlcokingQueue实际上用的生产这消费者模型。我们知道生产者消费者模型一般有两种实现方式,可以利用信号量也可以利用条件变量实现,muduo库采用条件变量实现。

BlockingQueue比较简单,它是线程安全的,我们在外部调用它时无需加锁。


它的类图如下:



实现代码如下:

#ifndef MUDUO_BASE_BLOCKINGQUEUE_H  
#define MUDUO_BASE_BLOCKINGQUEUE_H  
  
#include <muduo/base/Condition.h>  
#include <muduo/base/Mutex.h>  
  
#include <boost/noncopyable.hpp>  
#include <deque>  
#include <assert.h>  
  
namespace muduo  
{  
  
template<typename T>  
class BlockingQueue : boost::noncopyable  
{  
 public:  
  BlockingQueue()  
    : mutex_(),  
      notEmpty_(mutex_),  
      queue_()    //使用deque  
  {  
  }  
  
  void put(const T& x)    //往阻塞队列放任务  
  {  
    MutexLockGuard lock(mutex_);  
    queue_.push_back(x);  
    notEmpty_.notify(); // wait morphing saves us     //不空唤醒  
    // http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/  
  }  
  
#ifdef __GXX_EXPERIMENTAL_CXX0X__  
  void put(T&& x)  
  {  
    MutexLockGuard lock(mutex_);  
    queue_.push_back(std::move(x));  
    notEmpty_.notify();  
  }  
  // FIXME: emplace()  
#endif  
  
  T take()    //取任务  
  {  
    MutexLockGuard lock(mutex_);     //取任务时也要保证线程安全  
    // always use a while-loop, due to spurious wakeup  
    while (queue_.empty())    //如果为空就阻塞在这里啦,用while循环不必多说  
    {  
      notEmpty_.wait();  
    }  
    assert(!queue_.empty());    //确保队列不空  
#ifdef __GXX_EXPERIMENTAL_CXX0X__  
    T front(std::move(queue_.front()));  
#else  
    T front(queue_.front());   //取出队头  
#endif  
    queue_.pop_front();    //弹出队头。  
    return front;   //返回  
  }  
  
  size_t size() const     //返回队列大小  
  {  
    MutexLockGuard lock(mutex_);  
    return queue_.size();  
  }  
  
 private:  
  mutable MutexLock mutex_;  
  Condition         notEmpty_;  
  std::deque<T>     queue_;  
};  
  
}  
  
#endif  // MUDUO_BASE_BLOCKINGQUEUE_H  

二:有界阻塞队列

BoundBlockingQueue有界阻塞队列,实际上就是实现了一个循环队列。功能和上面的BlockingQueue都是一样的。

它的类图如下:



muduo库实现该队列实际上是内部把boost::circular_buffer类作为底层数据结构实现的。

实现:
#ifndef MUDUO_BASE_BOUNDEDBLOCKINGQUEUE_H  
#define MUDUO_BASE_BOUNDEDBLOCKINGQUEUE_H  
  
#include <muduo/base/Condition.h>  
#include <muduo/base/Mutex.h>  
  
#include <boost/circular_buffer.hpp>  
#include <boost/noncopyable.hpp>  
#include <assert.h>  
  
namespace muduo  
{  
  
template<typename T>  
class BoundedBlockingQueue : boost::noncopyable  
{  
 public:  
  explicit BoundedBlockingQueue(int maxSize)  
    : mutex_(),  
      notEmpty_(mutex_),  
      notFull_(mutex_),  
      queue_(maxSize)  
  {  
  }  
  
  void put(const T& x)  
  {  
    MutexLockGuard lock(mutex_);  
    while (queue_.full())  
    {  
      notFull_.wait();  
    }  
    assert(!queue_.full());  
    queue_.push_back(x);  
    notEmpty_.notify();  
  }  
  
  T take()  
  {  
    MutexLockGuard lock(mutex_);  
    while (queue_.empty())  
    {  
      notEmpty_.wait();  
    }  
    assert(!queue_.empty());  
    T front(queue_.front());  
    queue_.pop_front();  
    notFull_.notify();  
    return front;  
  }  
  
  bool empty() const  
  {  
    MutexLockGuard lock(mutex_);  
    return queue_.empty();  
  }  
  
  bool full() const  
  {  
    MutexLockGuard lock(mutex_);  
    return queue_.full();  
  }  
  
  size_t size() const     //返回大小  
  {  
    MutexLockGuard lock(mutex_);  
    return queue_.size();  
  }  
  
  size_t capacity() const     //返回容量  
  {  
    MutexLockGuard lock(mutex_);  
    return queue_.capacity();  
  }  
  
 private:  
  mutable MutexLock          mutex_;  
  Condition                  notEmpty_;  
  Condition                  notFull_;  
  boost::circular_buffer<T>  queue_;      //使用boost的环形缓冲区  
};  
  
}  
  
#endif  // MUDUO_BASE_BOUNDEDBLOCKINGQUEUE_H 
所以说这两个阻塞队列其实没啥区别,只是底层采用不同数据结构存储数据而已。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值