ring-buffer(C 语言实现)
2013-12-18 14:57
288 查看
下面是一个 ring-buffer 的 C 语言实现,采用
Mirroring 方式实现空、满判断。通过 void 指针模拟泛型,可以在初始化时灵活定义 ring-buffer 中的元素类型(例如 char 类型,int 类型,数组类型,结构体类型等)。
首先给出头文件定义:
下面是对应的 C 文件:
最后给出一个简单的应用示例,将字符数组写入 ring-buffer,然后读出、显示:
Mirroring 方式实现空、满判断。通过 void 指针模拟泛型,可以在初始化时灵活定义 ring-buffer 中的元素类型(例如 char 类型,int 类型,数组类型,结构体类型等)。
首先给出头文件定义:
/** * File: ring_buf.h * * Description: * Header file for ring-buffer. * Implemented according to the 'Mirroring' solution: * http://en.wikipedia.org/wiki/Circular_buffer#Mirroring * * Change Logs: * Date Author Notes * 2013-12-16 Glen first implementation */ #ifndef _RING_BUF_H_ #define _RING_BUF_H_ #include <stdint.h> #include <stdbool.h> #include <stddef.h> #define IDX_MASK (SIZE_MAX>>1) #define MSB_MASK (~IDX_MASK) /* also the maximum value of the buffer depth */ /* ring buffer structure */ struct ring_buf { size_t depth ; /* maximum element number */ size_t width ; /* sizeof each element */ size_t rd_idx; /* MSB is used for the 'mirror' flag */ size_t wr_idx; /* MSB is used for the 'mirror' flag */ void *buf ; }; typedef struct ring_buf ring_buf_t; typedef struct ring_buf* ring_buf_p; bool ring_buf_init (ring_buf_p rbuf, size_t depth, size_t width); void ring_buf_free (ring_buf_p rbuf); void ring_buf_clear(ring_buf_p rbuf); bool ring_buf_full (ring_buf_p rbuf); bool ring_buf_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); #endif
下面是对应的 C 文件:
/** * File: ring_buf.c * * Description: * Ring-buffer implemented according to the 'Mirroring' solution: * http://en.wikipedia.org/wiki/Circular_buffer#Mirroring * * Change Logs: * Date Author Notes * 2013-12-16 Glen first implementation */ #include "ring_buf.h" #include <stdlib.h> #include <string.h> #include <assert.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, size_t depth, size_t width) { assert(depth > 0 && depth < MSB_MASK && width > 0); rbuf->depth = depth; rbuf->width = width; rbuf->rd_idx = 0; rbuf->wr_idx = 0; rbuf->buf = calloc(depth, width); return rbuf->buf != NULL; } /** * @brief Release the ring-buffer object. Deallocate the buffer memory. * * @param rbuf: Pointer to the ring-buffer object */ void ring_buf_free(ring_buf_p rbuf) { free(rbuf->buf); rbuf->buf = NULL; } /** * @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 & IDX_MASK) == (rbuf->wr_idx & IDX_MASK) && (rbuf->rd_idx & MSB_MASK) != (rbuf->wr_idx & MSB_MASK); } /** * @brief Increase the buffer index while writing or reading the ring-buffer. * This is implemented according to the 'mirroring' solution: * http://en.wikipedia.org/wiki/Circular_buffer#Mirroring * * @param rbuf : Pointer to the ring-buffer * @param p_idx: Pointer to the buffer index to be increased */ inline void ring_buf_incr(ring_buf_p rbuf, size_t *p_idx) { size_t idx = *p_idx & IDX_MASK; size_t msb = *p_idx & MSB_MASK; if (++idx == rbuf->depth) { msb ^= MSB_MASK; idx = 0; } *p_idx = msb | idx; } /** * @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(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, rbuf->buf + rbuf->rd_idx * rbuf->width, rbuf->width); ring_buf_incr(rbuf, &rbuf->rd_idx); return true; } }
最后给出一个简单的应用示例,将字符数组写入 ring-buffer,然后读出、显示:
int main() { ring_buf_t rbuf; char str[10]; ring_buf_init(&rbuf, 8, sizeof(str)); ring_buf_write(&rbuf, "str 0"); ring_buf_write(&rbuf, "str 1"); ring_buf_write(&rbuf, "str 2"); ring_buf_write(&rbuf, "str 3"); int k = 0; for (k = 0; k < 8; k++) if (ring_buf_read(&rbuf, str)) printf("%s\n", str); ring_buf_free(&rbuf); return 0; }
相关文章推荐
- 算法:基于 RingBuffer 的 Queue 实现
- 循环缓冲实现(ring buffer/circular buffer)
- 环形缓冲区的实现原理(ring buffer)
- 网络字节流数据解析组件的设计与实现--Circular Buffer(Ring Buffer)
- Linux内核跟踪之ring buffer的实现【转】
- (转载)环形缓冲区的实现原理(ring buffer) .
- Ring Buffer 实现原理
- 环形缓冲区的实现原理(ring buffer)
- 线程安全的无锁RingBuffer的实现
- 线程安全的无锁RingBuffer的实现【多个写线程一个读线程】
- linux内核--使用内核队列实现ringbuffer(续)
- 线程安全的无锁RingBuffer的实现
- Ring Buffer 实现原理
- 循环队列——实现ringbuffer为了多媒体数据缓存
- Linux内核跟踪之ring buffer的实现
- Linux内核跟踪之ring buffer的实现
- 24、USART 使用 ringbuffer 实现无阻塞的读写
- c印记(八): ring buffer实现
- Ring buffer basics 环形缓冲基础(C语言实现) 二
- golang实现ringbuffer(不定长)