美文网首页
循环缓冲区

循环缓冲区

作者: 幕枫楚雨 | 来源:发表于2020-04-08 19:54 被阅读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);
    

    相关文章

      网友评论

          本文标题:循环缓冲区

          本文链接:https://www.haomeiwen.com/subject/eestmhtx.html