參考
圓形緩沖區(qū)(循環(huán)buffer)實(shí)現(xiàn)
35.Linux-分析并制作環(huán)形緩沖區(qū)
環(huán)形緩沖區(qū)構(gòu)成
一般的毛甲,圓形緩沖區(qū)需要4個(gè)指針:
1.在內(nèi)存中實(shí)際開始位置;
2.在內(nèi)存中實(shí)際結(jié)束位置辈毯,也可以用緩沖區(qū)長度代替;
3.存儲(chǔ)在緩沖區(qū)中的有效數(shù)據(jù)的開始位置(讀指針)空闲;
4.存儲(chǔ)在緩沖區(qū)中的有效數(shù)據(jù)的結(jié)尾位置(寫指針)扁达。區(qū)分緩沖區(qū)滿或者空
鏡像指示位:
緩沖區(qū)的長度如果是n掌敬,邏輯地址空間則為0至n-1惯豆;那么,規(guī)定n至2n-1為鏡像邏輯地址空間奔害。本策略規(guī)定讀寫指針的地址空間為0至2n-1楷兽,其中低半部分對(duì)應(yīng)于常規(guī)的邏輯地址空間,高半部分對(duì)應(yīng)于鏡像邏輯地址空間华临。當(dāng)指針值大于等于2n時(shí)芯杀,使其折返(wrapped)到ptr-2n。使用一位表示寫指針或讀指針是否進(jìn)入了虛擬的鏡像存儲(chǔ)區(qū):置位表示進(jìn)入雅潭,不置位表示沒進(jìn)入還在基本存儲(chǔ)區(qū)揭厚。
在讀寫指針的值相同情況下,如果二者的指示位相同扶供,說明緩沖區(qū)為空筛圆;如果二者的指示位不同,說明緩沖區(qū)為滿椿浓。這種方法優(yōu)點(diǎn)是測(cè)試緩沖區(qū)滿/空很簡(jiǎn)單太援;不需要做取余數(shù)操作;讀寫線程可以分別設(shè)計(jì)專用[算法]策略扳碍,能實(shí)現(xiàn)精致的并發(fā)控制提岔。 缺點(diǎn)是讀寫指針各需要額外的一位作為指示位。
如果緩沖區(qū)長度是2的[冪]笋敞,則本方法可以省略鏡像指示位碱蒙。如果讀寫指針的值相等,則緩沖區(qū)為空夯巷;如果讀寫指針相差n振亮,則緩沖區(qū)為滿,這可以用條件表達(dá)式(寫指針 == (讀指針 [異或] 緩沖區(qū)長度))來判斷鞭莽。
代碼
- 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);
- 寫數(shù)據(jù)
向緩沖區(qū)寫數(shù)據(jù)坊秸,寫滿將覆蓋最早的數(shù)據(jù)
if(CicbufIsInvalid(&cicbuf) != 0)
{
CicbufWrite(&cicbuf, (ElemType *)elemtype);
}
- 讀數(shù)據(jù)
讀緩沖區(qū),如果空則退出
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);