《一个简易的数据帧缓冲队列 (一)》
《数据帧缓冲队列(继上一篇的简单队列,改进)(二)》
《数据帧缓冲队列(改进,数据可视化)(三)》
继上一篇简单队列,进行改进:
1.0 一次性申请空间,避免频繁malloc和free
2.0 多线程可以同时读写 不同的区域
3.0 写数据不会阻塞,覆盖最老的数据
代码:
queue.h
#ifndef __QUEUE_HEAD_H__
#define __QUEUE_HEAD_H__
#include <pthread.h>
#include <semaphore.h>
typedef unsigned char uint8_t; //无符号8位数
#define MIN(a,b) (a)<(b)?(a):(b)
#define SIGLEFRAME_LEN (1024*125) //125K
typedef struct _QUEUE_NODE_
{
pthread_mutex_t mlock;
int datalen;
uint8_t data[SIGLEFRAME_LEN];
} QUEUE_NODE;
class CQueue
{
public :
CQueue(int frames);
~CQueue();
/*
*\\ pram: data, the src data, len , the src data lenth
*\\ return : real input data lenth
*/
int pop(uint8_t *data,int len);
/*
* \\no block
*\\ pram: data, the dest data buffer, len , dest data buffer lenth,
*\\ return : real output data lenth
*/
int push(uint8_t *data,int len);
/*
* \\ breif :get the data buffer pointer whith block, Manual release is required after use
*\\ param : **pdata , *plen :the queue data len
*\\ return -1; no data to get. other the que index will be return ,
*/
int getbuffer(uint8_t **pdata,int *plen);
/*
*\\ breif : get back the que data buffer
*\\ pram:the que index
*\\ return : 0
*/
int releasebuffer(int index);
private:
void addInindex();
void addOutindex();
int IncreaseEffectives();
int reduceEffectives();
private:
int maxFrames;
QUEUE_NODE *que;
int mInindex;
int mOutindex;
int mEffectives;
sem_t mSem;
pthread_mutex_t mIndexlock;
};
#endif
queue.cpp
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include "Queue.h"
#define LOOP_ADD(i,r) ((i)+1)>=(r)?0:(i+1)
#define ERRO_INFO(fmt, args...) do {printf("[%s,%s,%d]",__FILE__,__FUNCTION__,__LINE__);printf(fmt,##args);} while(0)
#if 1
#define DEBUG(fmt, args...) do {printf("[%s,%s,%d]",__FILE__,__FUNCTION__,__LINE__);printf(fmt,##args);} while(0)
#else
#define DEBUG(fmt, args...)
#endif
CQueue::CQueue(int frames):
maxFrames(frames),
mInindex(0),
mOutindex(0),
mEffectives(0)
{
que = (QUEUE_NODE *)malloc(frames*sizeof(QUEUE_NODE));
if(que == NULL)
{
printf("erro to malloc\n");
}
pthread_mutexattr_t mutextattr;
pthread_mutexattr_init(&mutextattr);
// 设置互斥锁在进程之间共享
pthread_mutexattr_setpshared(&mutextattr, PTHREAD_PROCESS_SHARED);
int i =0;
for(i=0;i<maxFrames;i++)
{
pthread_mutex_init(&que[i].mlock, &mutextattr);
}
pthread_mutex_init(&mIndexlock, &mutextattr);
sem_init(&mSem, 0, 0);
}
CQueue::~CQueue()
{
int i =0;
for(i=0;i<maxFrames;i++)
{
pthread_mutex_destroy(&que[i].mlock);
}
pthread_mutex_destroy(&mIndexlock);
sem_destroy(&mSem);
if(que != NULL)
{
free(que);
que = NULL;
}
}
int CQueue::pop(uint8_t *data,int len)
{
//DEBUG("in %d out %d len %d\n ",mInindex,mOutindex,len);
//sem_wait(&mSem);
sem_trywait(&mSem);
int iout = mOutindex;
pthread_mutex_t * ilock = &que[iout].mlock;
pthread_mutex_lock(ilock);
if(reduceEffectives() ==0)
{
mEffectives = 0;
pthread_mutex_unlock(ilock);
DEBUG("no data\n");
return 0;
}
int copylen = MIN(len,que[iout].datalen);
if(data != NULL)
{
memcpy(data,que[iout].data,copylen);
}
addOutindex();
pthread_mutex_unlock(ilock);
return copylen;
}
int CQueue::push(uint8_t *data,int len)
{
//DEBUG("in %d out %d len %d\n ",mInindex,mOutindex,len);
int iIn = mInindex;
pthread_mutex_t * ilock = &que[iIn].mlock;
pthread_mutex_lock(ilock);
int copylen = MIN(len,sizeof(que[iIn].data));
if(data != NULL)
{
memcpy(que[iIn].data,data,copylen);
que[iIn].datalen = copylen;
}
addInindex();
sem_post(&mSem);
if(IncreaseEffectives() == maxFrames)
{//覆盖老数据
DEBUG("cover mEffectives %d ,maxFrames %d\n",mEffectives,maxFrames);
//DEBUG("cover mInindex %d ,mOutindex %d\n",mInindex,mOutindex);
sem_trywait(&mSem);
addOutindex();
}
pthread_mutex_unlock(ilock);
return copylen;
}
int CQueue::getbuffer(uint8_t **pdata,int *plen)
{
int val=0;
sem_wait(&mSem);
int iout = mOutindex;
pthread_mutex_t * ilock = &que[iout].mlock;
pthread_mutex_lock(ilock);
//DEBUG("pop mEffectives %d ,maxFrames %d\n",mEffectives,maxFrames);
if(reduceEffectives() ==0 )
{
*pdata = NULL;
*plen = 0;
pthread_mutex_unlock(ilock);
DEBUG("no data\n");
return -1;
}
*pdata = que[iout].data;
*plen = que[iout].datalen;
addOutindex();
//DEBUG("in %d out %d len %d unlock \n ",mInindex,mOutindex,len);
//pthread_mutex_unlock(ilock);
//DEBUG("get index %d \n",iout);
return iout;
}
int CQueue::releasebuffer(int index)
{
//DEBUG("releas %d \n",index);
if(0 <= index && index < maxFrames)
{
pthread_mutex_unlock(&que[index].mlock);
}
return 0;
}
void CQueue::addInindex()
{
pthread_mutex_lock(&mIndexlock);
mInindex = LOOP_ADD(mInindex,maxFrames);
pthread_mutex_unlock(&mIndexlock);
}
void CQueue::addOutindex()
{
pthread_mutex_lock(&mIndexlock);
mOutindex = LOOP_ADD(mOutindex,maxFrames);
pthread_mutex_unlock(&mIndexlock);
}
int CQueue::IncreaseEffectives()
{
pthread_mutex_lock(&mIndexlock);
int ret = mEffectives;
mEffectives += 1;
if(mEffectives > maxFrames)
{
mEffectives = maxFrames;
}
pthread_mutex_unlock(&mIndexlock);
return ret;
}
int CQueue::reduceEffectives()
{
pthread_mutex_lock(&mIndexlock);
int ret = mEffectives;
mEffectives -= 1;
if(mEffectives<0)
{
mEffectives = 0;
}
pthread_mutex_unlock(&mIndexlock);
return ret;
}
#if 0
int main()
{
CQueue * pQueue = new CQueue(3);
uint8_t buf1[128]="11111";
uint8_t buf2[128]="22222";
uint8_t buf3[128]="33333";
uint8_t buf4[128]="44444";
uint8_t buf5[128]="55555";
uint8_t bufget[128]={0};
int len = sizeof(bufget);
pQueue->push(buf1,sizeof(buf1));
#if 1
pQueue->push(buf2,sizeof(buf2));
pQueue->push(buf3,sizeof(buf3));
pQueue->push(buf4,sizeof(buf4));
pQueue->push(buf5,sizeof(buf5));
pQueue->pop(bufget,len);
printf("wang bufget :%s \n",bufget);
pQueue->pop(bufget,len);
printf("wang bufget :%s \n",bufget);
pQueue->pop(bufget,len);
printf("wang bufget :%s \n",bufget);
pQueue->pop(bufget,len);
printf("wang bufget :%s \n",bufget);
pQueue->pop(bufget,len);
printf("wang bufget :%s \n",bufget);
//pQueue->push(buf1,sizeof(buf1));
//len = sizeof(bufget);
#endif
//pQueue->pop(bufget,len);
//printf("wang bufget :%s \n",bufget);
delete pQueue;
return 0;
}
#endif