C语言循环队列实现

在嵌入式开发中,有时候数据收发速度和处理速度差别较大,若支持处理收发耗时较长,可能导致数据丢失或者增大系统响应时间。使用循环队列先把需要收发的数据存入队列,再在系统空闲是处理收发任务,可很好的解决以上的问题


循环队列原理:

参见博客 循环队列的原理


C代码实现:

ring_buf.h

/**
 * File: ring_buf.h
 *   Date           Author       Notes
 *   2020-11-25     dave
 */

#ifndef _RING_BUF_H_
#define _RING_BUF_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>

/* ring buffer structure */

typedef struct ring_buf
{
    size_t depth ;             /* maximum element number */
    size_t width ;             /* sizeof each element */
    size_t rd_idx;             
    size_t wr_idx;             
    void   *buf  ;
}ring_buf_t,*ring_buf_p;

bool ring_buf_init (ring_buf_p rbuf, void *buf,size_t depth, size_t width);
void ring_buf_clear(ring_buf_p rbuf);
bool ring_buf_is_full (ring_buf_p rbuf);
bool ring_buf_is_empty(ring_buf_p rbuf);

bool ring_buf_write(ring_buf_p rbuf, void *wr_data);
bool ring_buf_read (ring_buf_p rbuf, void *rd_data);

size_t ring_buf_item_count(ring_buf_p rbuf);
size_t ring_buf_left_count(ring_buf_p rbuf);

bool ring_buf_item_search(ring_buf_p rbuf,void *search_data,size_t*index);
bool ring_buf_item_copy(ring_buf_p rbuf,void *buf,size_t count);
bool ring_buf_item_remove(ring_buf_p rbuf,size_t count);
bool ring_buf_item_write(ring_buf_p rbuf, void *wr_data,size_t count);
bool ring_buf_item_read(ring_buf_p rbuf, void *rd_data,size_t count);

#ifdef __cplusplus
 }
#endif

#endif

ring_buf.c

/**
 * File: ring_buf.c
 *   Date           Author       Notes
 *   2020-11-25     dave
 */

#include "ring_buf.h"

/**
 * @brief  Initialize the ring-buffer. Allocate necessary memory for the buffer.
 *
 * @param  rbuf : Pointer to the ring-buffer object
 * @param  depth: Maximum element number of the buffer
 * @param  width: sizeof each element
 *
 * @return true : Succeeded
 *         false: Failed
 */
bool ring_buf_init(ring_buf_p rbuf, void *buf, size_t depth, size_t width)
{
    if ((depth > 0) && (width > 0))
    {
        rbuf->depth = depth;
        rbuf->width = width;
        rbuf->rd_idx = 0;
        rbuf->wr_idx = 0;
        rbuf->buf = buf;
        return rbuf->buf != NULL;
    }
    else
    {
       return false;
    }
}


/**
 * @brief  Clear the ring-buffer object.
 *
 * @param  rbuf: Pointer to the ring-buffer object
 */
void ring_buf_clear(ring_buf_p rbuf)
{
    rbuf->rd_idx = 0;
    rbuf->wr_idx = 0;
}

/**
 * @brief  Whether the ring-buffer is empty or not.
 *
 * @param  rbuf: Pointer to the ring-buffer
 *
 * @return true : Empty. There's no elements stored in the buffer.
 *         false: Not empty
 */
bool ring_buf_is_empty(ring_buf_p rbuf)
{
    return rbuf->rd_idx == rbuf->wr_idx;
}

/**
 * @brief  Whether the ring-buffer is full or not.
 *
 * @param  rbuf: Pointer to the ring-buffer
 *
 * @return true : Full
 *         false: Not full
 */
bool ring_buf_is_full(ring_buf_p rbuf)
{
    return (rbuf->rd_idx == (rbuf->wr_idx + 1)%rbuf->depth);
}

/**
 * @brief  Increase the buffer index while writing or reading the ring-buffer.
 * @param  rbuf : Pointer to the ring-buffer
 * @param  p_idx: Pointer to the buffer index to be increased
 */
static void ring_buf_incr(ring_buf_p rbuf, size_t *p_idx)
{
    *p_idx = (*p_idx + 1) % rbuf->depth;
}

/**
 * @brief  Write new element to the ring-buffer.
 *
 * @param  rbuf   : Pointer to the ring-buffer object
 * @param  wr_data: Pointer of the new element to be written to the buffer
 *
 * @return true : Succeeded
 *         false: Failed
 */
bool ring_buf_write(ring_buf_p rbuf, void *wr_data)
{
    if (ring_buf_is_full(rbuf))
    {
        return false;
    }
    else 
    {
        memcpy(((char*)rbuf->buf + rbuf->wr_idx * rbuf->width), wr_data, rbuf->width);
        ring_buf_incr(rbuf, &rbuf->wr_idx);
        return true;
    }
}

/**
 * @brief  Read from the ring-buffer
 *
 * @param  rbuf   : Pointer to the ring-buffer object
 * @param  rd_data: Pointer to the read result
 *
 * @return true : Succeeded
 *         false: Failed
 */
bool ring_buf_read(ring_buf_p rbuf, void *rd_data)
{
    if (ring_buf_is_empty(rbuf))
    {
        return false;
    }
    else 
    {
        memcpy(rd_data, ((char*)rbuf->buf + rbuf->rd_idx * rbuf->width), rbuf->width);
        ring_buf_incr(rbuf, &rbuf->rd_idx);
        return true;
    }
}

/**
 * @brief  get the ring-buffer item count
 *
 * @param  rbuf   : Pointer to the ring-buffer object
 *
 * @return item count
 */
size_t ring_buf_item_count(ring_buf_p rbuf)
{
    return ((rbuf->wr_idx - rbuf->rd_idx + rbuf->depth) % rbuf->depth);
}

/**
 * @brief  get the ring-buffer left count
 *
 * @param  rbuf : Pointer to the ring-buffer object
 *
 * @return left count
 */
size_t ring_buf_left_count(ring_buf_p rbuf)
{
    return (rbuf->depth - ring_buf_item_count(rbuf) - 1);
}

/**
 * @brief  search the ring-buffer item
 *
 * @param  rbuf   : Pointer to the ring-buffer object
 *
 * @return item number(0,1,2...)
 */
bool ring_buf_item_search(ring_buf_p rbuf,void *search_data,size_t*index)
{
    for(size_t i = 0;i < ring_buf_item_count(rbuf);i++)
    {
        void *pdata = (char*)rbuf->buf + ((rbuf->rd_idx + i)%rbuf->depth) * rbuf->width;
        
        if(memcmp(pdata,search_data,rbuf->width) == 0)
        {
            *index = i;
            return true;
        }
    }
    return false;    
}

/**
 * @brief  copy the ring-buffer item
 *
 * @param  rbuf   : Pointer to the ring-buffer object
 *
 * @return item count
 */
bool ring_buf_item_copy(ring_buf_p rbuf,void *buf,size_t count)
{
    if(count <= ring_buf_item_count(rbuf))
    {
        size_t cpy_idx = rbuf->rd_idx;
        for(size_t i = 0;i < count;i++)
        {
            memcpy((char*)buf + i*rbuf->width, ((char*)rbuf->buf + cpy_idx), rbuf->width);
            cpy_idx =  (cpy_idx + 1)% rbuf->depth;
        }
        return true;
    }
    else
    {
        return false;
    }
}


/**
 * @brief  remove the ring-buffer item
 *
 * @param  rbuf   : Pointer to the ring-buffer object
 *
 * @return item count
 */
bool ring_buf_item_remove(ring_buf_p rbuf,size_t count)
{
    if(count <= ring_buf_item_count(rbuf))
    {
        rbuf->rd_idx = (rbuf->rd_idx + count)%rbuf->depth;
        return true;
    }
    else
    {
        return false;
    }
}


/**
 * @brief  Write  to the ring-buffer.
 *
 * @param  rbuf   : Pointer to the ring-buffer object
 * @param  wr_data: Pointer of the new element to be written to the buffer
 *
 * @return true : Succeeded
 *         false: Failed
 */
bool ring_buf_item_write(ring_buf_p rbuf, void *wr_data,size_t count)
{
    if(count > ring_buf_left_count(rbuf))
    {
        return false;
    }
    else 
    {
        for(size_t i = 0;i < count;i++)
        {
            memcpy(((char*)rbuf->buf + rbuf->wr_idx *rbuf->width), (char*)wr_data + i *rbuf->width ,rbuf->width);
            ring_buf_incr(rbuf, &rbuf->wr_idx);
        }
        return true;
    }
}

/**
 * @brief  Read from the ring-buffer
 *
 * @param  rbuf   : Pointer to the ring-buffer object
 * @param  rd_data: Pointer to the read result
 *
 * @return true : Succeeded
 *         false: Failed
 */
bool ring_buf_item_read(ring_buf_p rbuf, void *rd_data,size_t count)
{
    if(count <= ring_buf_item_count(rbuf))
    {
        for(size_t i = 0;i < count;i++)
        {
            memcpy((char*)rd_data + i*rbuf->width, ((char*)rbuf->buf + rbuf->rd_idx *rbuf->width), rbuf->width);
            ring_buf_incr(rbuf, &rbuf->rd_idx);
        }
        return true;
    }
    else
    {
        return false;
    }
}

不足之处,多多指正。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值