循环缓冲区
2020-04-08 本文已影响0人
幕枫楚雨
参考
圆形缓冲区(循环buffer)实现
35.Linux-分析并制作环形缓冲区
-
环形缓冲区构成
一般的,圆形缓冲区需要4个指针:
1.在内存中实际开始位置;
2.在内存中实际结束位置,也可以用缓冲区长度代替;
3.存储在缓冲区中的有效数据的开始位置(读指针);
4.存储在缓冲区中的有效数据的结尾位置(写指针)。 -
区分缓冲区满或者空
镜像指示位:
缓冲区的长度如果是n,逻辑地址空间则为0至n-1;那么,规定n至2n-1为镜像逻辑地址空间。本策略规定读写指针的地址空间为0至2n-1,其中低半部分对应于常规的逻辑地址空间,高半部分对应于镜像逻辑地址空间。当指针值大于等于2n时,使其折返(wrapped)到ptr-2n。使用一位表示写指针或读指针是否进入了虚拟的镜像存储区:置位表示进入,不置位表示没进入还在基本存储区。
在读写指针的值相同情况下,如果二者的指示位相同,说明缓冲区为空;如果二者的指示位不同,说明缓冲区为满。这种方法优点是测试缓冲区满/空很简单;不需要做取余数操作;读写线程可以分别设计专用[算法]策略,能实现精致的并发控制。 缺点是读写指针各需要额外的一位作为指示位。
如果缓冲区长度是2的[幂],则本方法可以省略镜像指示位。如果读写指针的值相等,则缓冲区为空;如果读写指针相差n,则缓冲区为满,这可以用条件表达式(写指针 == (读指针 [异或] 缓冲区长度))来判断。
代码
- ProductCircularBuffer.h
#ifndef __PRODUCT_CIRCULAR_BUFFER_H__
#define __PRODUCT_CIRCULAR_BUFFER_H__
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */
/********************************** include **********************************/
#include "hi_type.h"
/***************************** Macro Definition ******************************/
//#define
/*************************** Structure Definition ****************************/
//typedef struct
typedef struct {
HI_U64 videoPts;
HI_U32 videoLen;
HI_U32 pVideoAddr;
HI_U32 videoFrame;
} ElemType;
/* Circular buffer object */
typedef struct {
int size; /* maximum number of elements */
int start; /* index of oldest element */
int end; /* index at which to write new element */
ElemType *elems; /* vector of elements */
} CircularBuffer;
/****************************************function****************************************/
/**function: CicbufInit()
* description: cicbuf Init
*/
void CicbufInit(CircularBuffer *cb, int size);
/**function: CicbufDeInit()
* description: cicbuf DeInit
* if deinit, can not used cicbuf
*/
void CicbufDeInit(CircularBuffer *cb);
/**function: CicbufIsFull()
* description: judge cicbuf full
* return: [1]-full, [0]-not full;
*/
int CicbufIsFull(CircularBuffer *cb);
/**function: CicbufIsEmpty()
* description: judge cicbuf empty
* return: [1]-empty, [0]-not empty;
*/
int CicbufIsEmpty(CircularBuffer *cb);
/**function: CicbufIsInvalid()
* description: judge cicbuf invalid
* return: [0]-invalid, [other]-valid;
*/
int CicbufIsInvalid(CircularBuffer *cb);
/**function: CicbufSetValid()
* description: set cicbuf invalid
*/
void CicbufSetValid(CircularBuffer *cb);
/**function: CicbufWrite()
* description: write cicbuf
*/
void CicbufWrite(CircularBuffer *cb, ElemType *elem);
/**function: CicbufRead()
* description: read cicbuf
*/
void CicbufRead(CircularBuffer *cb, ElemType *elem);
/**function: CicbufGetData()
* description: get cicbuf data
*/
void CicbufGetData(CircularBuffer *cb, ElemType *elem);
/**function: CicbufRemoveData()
* description: remove cicbuf data
*/
void CicbufRemoveData(CircularBuffer *cb);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */
#endif /* End of #ifndef __PRODUCT_CIRCULAR_BUFFER_H__ */
- ProductCircularBuffer.c
/********************************** include **********************************/
#include <stdlib.h>
#include <unistd.h>
#include "ProductCircularBuffer.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */
/***************************** Macro Definition ******************************/
//#define
/*************************** Structure Definition ****************************/
//typedef struct
/***************************** Global Definition *****************************/
/***************************** Static Definition *****************************/
//static
/**********************************function*********************************/
/**function: CicbufInit()
* description: cicbuf Init
*/
void CicbufInit(CircularBuffer *cb, int size)
{
cb->size = size;
cb->start = 0;
cb->end = 0;
cb->elems = (ElemType *)calloc(cb->size, sizeof(ElemType));
}
/**function: CicbufDeInit()
* description: cicbuf DeInit
* if deinit, can not used cicbuf
*/
void CicbufDeInit(CircularBuffer *cb)
{
cb->size = 0;
cb->start = 0;
cb->end = 0;
free(cb->elems);
}
/**function: CicbufPrint()
* description: cicbuf print info
*/
static void CicbufPrint(CircularBuffer *cb)
{
printf("size=0x%x, start=%d, end=%d\n", cb->size, cb->start, cb->end);
}
/**function: CicbufIsFull()
* description: judge cicbuf full
* return: [1]-full, [0]-not full;
*/
int CicbufIsFull(CircularBuffer *cb)
{
return cb->end == (cb->start ^ cb->size); /* This inverts the most significant bit of start before comparison */
}
/**function: CicbufIsEmpty()
* description: judge cicbuf empty
* return: [1]-empty, [0]-not empty;
*/
int CicbufIsEmpty(CircularBuffer *cb)
{
//cbPrint(cb);
return cb->end == cb->start;
}
/**function: CicbufIsInvalid()
* description: judge cicbuf invalid
* return: [0]-invalid, [other]-valid;
*/
int CicbufIsInvalid(CircularBuffer *cb)
{
return cb->size;
}
/**function: CicbufSetValid()
* description: set cicbuf invalid
*/
void CicbufSetValid(CircularBuffer *cb)
{
cb->size = 0;
}
/**function: CicbufIncr()
* description: cicbuf
*/
static int CicbufIncr(CircularBuffer *cb, int p)
{
return (p + 1)&(2*cb->size-1); /* start and end pointers incrementation is done modulo 2*size */
}
/**function: CicbufWrite()
* description: write cicbuf
*/
void CicbufWrite(CircularBuffer *cb, ElemType *elem)
{
cb->elems[cb->end&(cb->size-1)] = *elem;
if (CicbufIsFull(cb)) /* full, overwrite moves start pointer */
{
cb->start = CicbufIncr(cb, cb->start);
}
cb->end = CicbufIncr(cb, cb->end);
}
/**function: CicbufRead()
* description: read cicbuf
*/
void CicbufRead(CircularBuffer *cb, ElemType *elem)
{
*elem = cb->elems[cb->start&(cb->size-1)];
cb->start = CicbufIncr(cb, cb->start);
}
/**function: CicbufGetData()
* description: get cicbuf data
*/
void CicbufGetData(CircularBuffer *cb, ElemType *elem)
{
*elem = cb->elems[cb->start&(cb->size-1)];
}
/**function: CicbufRemoveData()
* description: remove cicbuf data
*/
void CicbufRemoveData(CircularBuffer *cb)
{
cb->start = CicbufIncr(cb, cb->start);
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */
- 初始化cicbuf
#define CIC_BUF_LEN 64
...
//init circularbuf
CicbufInit(&cicbuf, CIC_BUF_LEN);
- 写数据
向缓冲区写数据,写满将覆盖最早的数据
if(CicbufIsInvalid(&cicbuf) != 0)
{
CicbufWrite(&cicbuf, (ElemType *)elemtype);
}
- 读数据
读缓冲区,如果空则退出
if(CicbufIsEmpty(&cicbuf))
{
return 0;
}
CicbufRead(&cicbuf, (ElemType*)elemtype);
- 去初始化cicbuf
CicbufSetValid(&cicbuf);
//deinit circularbuf, need not used cicbuf, otherwise result in signal 6 & 11???
CicbufDeInit(&cicbuf);