打印
[方案相关]

环形缓存区ring_buffer

[复制链接]
101|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cashrwood|  楼主 | 2025-3-22 14:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <stdlib.h>
#include <string.h>
#include "ring_buffer.h"

/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/

#define RB_INDH(rb)                ((rb)->head & ((rb)->count - 1))
#define RB_INDT(rb)                ((rb)->tail & ((rb)->count - 1))

#if !defined(MAX)
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#if !defined(MIN)
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/

/*****************************************************************************
* Private functions
****************************************************************************/

/*****************************************************************************
* Public functions
****************************************************************************/

/**
* [url=home.php?mod=space&uid=247401]@brief[/url]        Resets the ring buffer to empty
* @param        RingBuff        : Pointer to ring buffer
* [url=home.php?mod=space&uid=266161]@return[/url]        Nothing
*/
void RingBuffer_Flush(RINGBUFF_T *RingBuff)
{
    RingBuff->head = RingBuff->tail = 0;
}

/**
* @brief        Return size the ring buffer
* @param        RingBuff        : Pointer to ring buffer
* @return        Size of the ring buffer in bytes
*/
int RingBuffer_GetSize(RINGBUFF_T *RingBuff)
{
    return RingBuff->count;
}

/**
* @brief        Return number of items in the ring buffer
* @param        RingBuff        : Pointer to ring buffer
* @return        Number of items in the ring buffer
*/
static int RingBuffer_GetCount(RINGBUFF_T *RingBuff)
{
    return RB_VHEAD(RingBuff) - RB_VTAIL(RingBuff);
}

/**
* @brief        Return number of free items in the ring buffer
* @param        RingBuff        : Pointer to ring buffer
* @return        Number of free items in the ring buffer
*/
static int RingBuffer_GetFree(RINGBUFF_T *RingBuff)
{
    return RingBuff->count - RingBuffer_GetCount(RingBuff);
}

/**
* @brief        Return number of items in the ring buffer
* @param        RingBuff        : Pointer to ring buffer
* @return        1 if the ring buffer is full, otherwise 0
*/
int RingBuffer_IsFull(RINGBUFF_T *RingBuff)
{
    return (RingBuffer_GetCount(RingBuff) >= RingBuff->count);
}

/**
* @brief        Return empty status of ring buffer
* @param        RingBuff        : Pointer to ring buffer
* @return        1 if the ring buffer is empty, otherwise 0
*/
int RingBuffer_IsEmpty(RINGBUFF_T *RingBuff)
{
    return RB_VHEAD(RingBuff) == RB_VTAIL(RingBuff);
}
/* Initialize ring buffer */
int RingBuffer_Init(RINGBUFF_T *RingBuff, void *buffer, int itemSize, int count)
{
    RingBuff->data = buffer;
    RingBuff->count = count;
    RingBuff->itemSz = itemSize;
    RingBuff->head = RingBuff->tail = 0;

    return 1;
}

/* Insert a single item into Ring Buffer */
int RingBuffer_Insert(RINGBUFF_T *RingBuff, const void *data)
{
    u8 *ptr = RingBuff->data;

    /* We cannot insert when queue is full */
    if (RingBuffer_IsFull(RingBuff))
        return 0;
    ptr += RB_INDH(RingBuff) * RingBuff->itemSz;
    memcpy(ptr, data, RingBuff->itemSz);
    RingBuff->head++;
    return 1;
}

/* Insert multiple items into Ring Buffer */
int RingBuffer_InsertMult(RINGBUFF_T *RingBuff, const void *data, int num)
{
    u8 *ptr = RingBuff->data;
    int cnt1, cnt2;

    /* We cannot insert when queue is full */
    if (RingBuffer_IsFull(RingBuff))
        return 0;

    /* Calculate the segment lengths */
    cnt1 = cnt2 = RingBuffer_GetFree(RingBuff);
    if (RB_INDH(RingBuff) + cnt1 >= RingBuff->count)
        cnt1 = RingBuff->count - RB_INDH(RingBuff);
    cnt2 -= cnt1;

    cnt1 = MIN(cnt1, num);
    num -= cnt1;

    cnt2 = MIN(cnt2, num);
    num -= cnt2;

    /* Write segment 1 */
    ptr += RB_INDH(RingBuff) * RingBuff->itemSz;
    memcpy(ptr, data, cnt1 * RingBuff->itemSz);
    RingBuff->head += cnt1;

    /* Write segment 2 */
    ptr = (u8 *) RingBuff->data + RB_INDH(RingBuff) * RingBuff->itemSz;
    data = (const u8 *) data + cnt1 * RingBuff->itemSz;
    memcpy(ptr, data, cnt2 * RingBuff->itemSz);
    RingBuff->head += cnt2;

    return cnt1 + cnt2;
}

/* Pop single item from Ring Buffer */
int RingBuffer_Pop(RINGBUFF_T *RingBuff, void *data)
{
    u8 *ptr = RingBuff->data;

    /* We cannot pop when queue is empty */
    if (RingBuffer_IsEmpty(RingBuff))
        return 0;

    ptr += RB_INDT(RingBuff) * RingBuff->itemSz;
    memcpy(data, ptr, RingBuff->itemSz);
    RingBuff->tail++;

    return 1;
}

/* Pop multiple items from Ring buffer */
int RingBuffer_PopMult(RINGBUFF_T *RingBuff, void *data, int num)
{
    u8 *ptr = RingBuff->data;
    int cnt1, cnt2;

    /* We cannot insert when queue is empty */
    if (RingBuffer_IsEmpty(RingBuff))
        return 0;

    /* Calculate the segment lengths */
    cnt1 = cnt2 = RingBuffer_GetCount(RingBuff);
    if (RB_INDT(RingBuff) + cnt1 >= RingBuff->count)
        cnt1 = RingBuff->count - RB_INDT(RingBuff);
    cnt2 -= cnt1;

    cnt1 = MIN(cnt1, num);
    num -= cnt1;

    cnt2 = MIN(cnt2, num);
    num -= cnt2;

    /* Write segment 1 */
    ptr += RB_INDT(RingBuff) * RingBuff->itemSz;
    memcpy(data, ptr, cnt1 * RingBuff->itemSz);
    RingBuff->tail += cnt1;

    /* Write segment 2 */
    ptr = (u8 *) RingBuff->data + RB_INDT(RingBuff) * RingBuff->itemSz;
    data = (u8 *) data + cnt1 * RingBuff->itemSz;
    memcpy(data, ptr, cnt2 * RingBuff->itemSz);
    RingBuff->tail += cnt2;

    return cnt1 + cnt2;
}


使用特权

评论回复
沙发
lidi911| | 2025-3-23 19:41 | 只看该作者
和FIFO buffer相比有什么区别。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

24

主题

1384

帖子

0

粉丝