#ifndef _CACHE_H_
#define _CACHE_H_
#include <pthread.h>
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <stdint.h>
#include <sys/time.h>
#include <string.h>
/*传入的数据类型T构造函数参数应该设置没有,否则编译出错*/
template<class T>
class CacheQueue
{
public:
CacheQueue(uint32_t bufSize);
void Push(const T *req);
const T *Pop(int timeout);
~CacheQueue();
private:
std::queue<T> _requests;
pthread_mutex_t _mutex;
pthread_cond_t _not_full_cond;
pthread_cond_t _not_empty_cond;
uint32_t _bufSize;
T *_req;
};
template<class T>
CacheQueue<T>::CacheQueue(uint32_t bufSize):_bufSize(bufSize)
{
_req = new T;
pthread_mutex_init(&_mutex, NULL);
pthread_cond_init(&_not_full_cond, NULL);
pthread_cond_init(&_not_empty_cond, NULL);
}
template<class T>
CacheQueue<T>::~CacheQueue()
{
if (_req != NULL)
delete _req;
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_not_full_cond);
pthread_cond_destroy(&_not_empty_cond);
}
template<class T>
void CacheQueue<T>::Push(const T *req)
{
pthread_mutex_lock(&_mutex);
while (_requests.size() == _bufSize)
{
pthread_cond_wait(&_not_full_cond, &_mutex);
}
_requests.push(*req);
pthread_cond_signal(&_not_empty_cond);
// 连续多次调用,如果没有线程正在等待该信号,也是相当于一次
pthread_mutex_unlock(&_mutex);
}
template<class T>
const T *CacheQueue<T>::Pop(int timeout)
{
int ret = 0;
pthread_mutex_lock(&_mutex);
struct timeval now;
struct timespec timepass;
gettimeofday(&now, NULL);
timepass.tv_sec = now.tv_sec + timeout; // 绝对系统时间
timepass.tv_nsec = 0;
while (ret == 0 && _requests.empty())
{
ret = pthread_cond_timedwait(&_not_empty_cond, &_mutex, &timepass);
printf("%s\n", strerror(ret));
}
if(ret!=0)
{
pthread_mutex_unlock(&_mutex);
return NULL;
}
T tmp = _requests.front();
memcpy(_req, &tmp, sizeof(T));
_requests.pop();
pthread_cond_signal(&_not_full_cond);
pthread_mutex_unlock(&_mutex);
return _req;
}
#endif
#include "cache.h"
class Data
{
public:
Data()
{
a = b= -1;
}
void set(int a, int b)
{
this->a = a;
this->b = b;
}
void print() const
{
printf("a: %d, b: %d\n", a, b);
}
private:
int a;
int b;
};
CacheQueue<Data> share(20);
void *push(void *arg)
{
Data d;
int a = 1, b = 1;
while(1)
{
d.set(a, b);
share.Push(&d);
a++;
b++;
usleep(2000*1000);
}
pthread_exit(NULL);
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, push, NULL);
while(1)
{
const Data *p = share.Pop(1);
if (p == NULL)
{
printf("no data.\n");
}else
{
p->print();
}
usleep(100*1000);
}
return 0;
}