这里,我们需要将缓冲区封装起来,然后让缓冲区与线程想连接,所以我们需要一个相应的接口。
在Buffer中,我们需要想对应的一把锁与两个条件变量。
当满足队列为空时,消费者等待,反之,生产者等待。
Buffer的声明如下:
1 #ifndef BUFFER_H 2 #define BUFFER_H 3 4 #include "NonCopyable.h" 5 #include "MutexLock.h" 6 #include "Condition.h" 7 #include <queue> 8 9 10 class Buffer : private NonCopyable 11 { 12 public: 13 14 Buffer(size_t queueSize); 15 16 void push(int val); 17 int pop(); 18 19 bool empty() const; 20 size_t size() const; 21 22 private: 23 24 mutable MutexLock _mutex; 25 Condition _full; 26 Condition _empty; 27 size_t _queueSize; 28 std::queue<int> _queue; 29 }; 30 31 32 #endif /*BUFFER_H*/
在这里,我们引用MutexLockGuard来解决忘记解锁的问题,当我们定义一个该类的对象时,·自动上锁,
当该对象销毁时,自动解锁。
当然,有一种使用方式是错误的,例如:
size_t Buffer::size() const { MutexLockGuard(mutex_); return queue_.size(); }
这段代码的加锁周期仅在那一行有效,所以该种方法是错误的,所以,我们定义一个宏(在Mutex.h文件中可找到):
#define MutexLockGuard(m) "Error"
这样当错误使用时,会导致编译错误,使我们早些发现问题。
cpp实现代码如下:
1 #include "Buffer.h" 2 #include "Thread.h" 3 using namespace std; 4 5 Buffer::Buffer(size_t queueSize) 6 :_full(_mutex), 7 _empty(_mutex), 8 _queueSize(queueSize) 9 { 10 11 } 12 13 bool Buffer::empty() const 14 { 15 MutexLockGuard lock(_mutex); 16 return _queue.empty(); 17 } 18 19 size_t Buffer::size() const 20 { 21 MutexLockGuard lock(_mutex); 22 return _queue.size(); 23 } 24 25 void Buffer::push(int val) 26 { 27 { 28 MutexLockGuard lock(_mutex); 29 while(_queue.size() > _queueSize) 30 _empty.wait(); 31 _queue.push(val); 32 } 33 _full.notify(); 34 } 35 36 int Buffer::pop() 37 { 38 int tmp = 0; 39 { 40 MutexLockGuard lock(_mutex); 41 while(_queue.empty()) 42 _full.wait(); 43 tmp = _queue.front(); 44 _queue.pop(); 45 } 46 _empty.notify(); 47 return tmp; 48 }