本文基于c++面对对象模式设计一个blockingqueue类,该类隐藏锁的一些细节,只提供给用户一些简单的接口,不理解生产者消费者模式不影响阅读。
template<typename T>
class blockingqueue
{
public:
blockingqueue(): deque_()
{
pthread_cond_init(&cond_,NULL);
pthread_mutex_init(&mutex_,NULL);
}
void put(const T& value)
{
pthread_mutex_lock(&mutex_);
deque_.push_back(value);
pthread_mutex_unlock(&mutex_);
pthread_cond_signal(&cond_);
}
T take()
{
pthread_mutex_lock(&mutex_);
while(deque_.empty())
pthread_cond_wait(&cond_, &mutex_);
T temp = deque_.front();
deque_.pop_front();
pthread_mutex_unlock(&mutex_);
return temp;
}
int size()
{
pthread_mutex_lock(&mutex_);
int size = deque_.size();
pthread_mutex_unlock(&mutex_);
return size;
}
private:
pthread_cond_t cond_;
pthread_mutex_t mutex_;
std::deque<T> deque_;
};
int size()
{
pthread_mutex_lock(&mutex_);
int size = deque_.size();
pthread_mutex_unlock(&mutex_);
return size;
}
private:
pthread_cond_t cond_;
pthread_mutex_t mutex_;
std::deque<T> deque_;
}
这个类提供给用户三个接口分别是:put()、take()、size()隐藏加锁和条件变量,内部有一个缓冲区deque,用户只需要通过从中添加和取数据即可。下面是测试代码:
#include <string>
#include <stdio.h>
#include <vector>
#include <queue>
#include <unistd.h>
#include <thread>
#include <functional>
#include <algorithm>
using namespace std::placeholders;
class Test
{
public:
Test(int m = 10)
{
for(int i = 0; i < m; ++i)
{
threads_.push_back(std::thread(&Test::Threadfunc, this));
}
}
void run(int times)
{
for(int i = 0; i < times; ++i)
{
char buf[32];
snprintf(buf, sizeof buf, "hello %d", i);
queue_.put(buf);
printf("tid=%d, put data = %s, size = %zd\n", std::this_thread::get_id(), buf, queue_.size());
sleep(1);
}
}
void joinAll()
{
for (size_t i = 0; i < threads_.size(); ++i)
{
queue_.put("stop");
}
for_each(threads_.begin(), threads_.end(), std::bind(&std::thread::join, _1));
}
private:
void Threadfunc()
{
printf("tid = %d started\n", std::this_thread::get_id());
bool running = true;
while (running)
{
sleep(1);
std::string d(queue_.take());
printf("tid=%d, get data = %s, size = %zd\n", std::this_thread::get_id(), d.c_str(), queue_.size());
running = (d != "stop");
}
printf("tid = %d stoped\n", std::this_thread::get_id());
}
blockingqueue<std::string> queue_;
std::vector<std::thread> threads_;
};
int main()
{
printf("maintid = %d\n", std::this_thread::get_id());
sleep(1);
Test t(5);
t.run(20);
t.joinAll();
return 0;
}