# CherryRingBuffer [English](./README.md) CherryRingBuffer 是一个的高效、易用的环形缓冲区,其原理与kfifo一致。 ## 简介 ### 1.创建并初始化一个RingBuffer ```c chry_ringbuffer_t rb; uint8_t mempool[1024]; int main(void) { /** * 需要注意的点是,init 函数第三个参数是内存池的大小(字节为单位) * 也是ringbuffer的深度,必须为 2 的幂次!!!。 * 例如 4、16、32、64、128、1024、8192、65536等 */ if(0 == chry_ringbuffer_init(&rb, mempool, 1024)){ printf("success\r\n"); }else{ printf("error\r\n"); } return 0; } ``` ### 2.生产者消费者模型的无锁使用 读和写的API除了overwrite外,如果满足ringbuffer只在一个线程里进行读,并且只在一个线程里面写,那么无须加锁,因为读和写操作只单独操作读或者写指针。 ```c void thread_producer(void* param) { char *data = "hello world"; while(1){ uint32_t len = chry_ringbuffer_write(&rb, data, 11); if(11 == len){ printf("[P] write success\r\n"); }else{ printf("[P] write faild, only write %d byte\r\n", len); } vTaskDelay(100); } } void thread_consumer(void* param) { char data[1024]; while(1){ uint32_t len =chry_ringbuffer_read(&rb, data, 11); if (len){ printf("[C] read success, read %d byte\r\n",len); data[11]='\0'; printf("%s\r\n",data); }else{ printf("[C] read faild, no data in ringbuffer\r\n"); } vTaskDelay(100); } } ``` ### 3. API简介 ```c /** * 用于清空,同时操作读写指针,多线程需要加锁 */ chry_ringbuffer_reset(&rb); /** * 用于清空,只操作读指针,在唯一的读线程调用无须加锁 */ chry_ringbuffer_reset_read(&rb); /** * 获取ringbuffer总大小(字节) */ uint32_t size = chry_ringbuffer_get_size(&rb); /** * 获取ringbuffer使用大小(字节) */ uint32_t used = chry_ringbuffer_get_used(&rb); /** * 获取ringbuffer空闲大小(字节) */ uint32_t free = chry_ringbuffer_get_free(&rb); /** * 检查ringbuffer是否为满,满返回true */ bool is_full = chry_ringbuffer_check_full(&rb); /** * 检查ringbuffer是否为空,空返回true */ bool is_empty = chry_ringbuffer_check_empty(&rb); uint8_t data = 0x55; /** * 写一字节 * 在唯一的写线程调用无须加锁 * 写成功返回true,满返回false */ chry_ringbuffer_write_byte(&rb, data); /** * 覆盖写一字节,当ringbuffer满的时候会覆盖最早的数据, * 非满情况与 chry_ringbuffer_write_byte 一致。 * 此API可能会同时操作读写指针,所以多线程需要加锁 * 始终返回true */ chry_ringbuffer_overwrite_byte(&rb, data); /** * 从ringbuffer中复制出来一字节 * 数据仍然保留在ringbuffer中 * 在唯一的读线程调用无须加锁 * 成功返回true,空返回false */ chry_ringbuffer_peek_byte(&rb, &data); /** * 从ringbuffer中读取出来一字节 * 数据从ringbuffer中取出 * 在唯一的读线程调用无须加锁 * 成功返回true,空返回false */ chry_ringbuffer_read_byte(&rb, &data); /** * 丢弃ringbuffer中一字节 * 数据从ringbuffer中取出 * 在唯一的读线程调用无须加锁 * 成功返回true,空返回false */ chry_ringbuffer_drop_byte(&rb); /** * 写多字节,其他与单字节写相同 * 返回实际写入的长度 */ chry_ringbuffer_write(&rb, data, 1); /** * 覆盖写多字节,其他与单字节覆盖写相同 * 返回实际写入的长度 */ chry_ringbuffer_overwrite(&rb, data, 1); /** * 复制多字节,其他与单字节复制相同 * 返回实际复制的长度 */ chry_ringbuffer_peek(&rb, data, 1); /** * 读取多字节,其他与单字节读取相同 * 返回实际读取的长度 */ chry_ringbuffer_read(&rb, data, 1); /** * 丢弃多字节,其他与单字节丢弃相同 * 返回实际丢弃的长度 */ chry_ringbuffer_drop(&rb, 1); void *pdata; uint32_t size; /** * 用于启动DMA,获取读取起始内存地址和最大线性可读取长度 */ pdata = chry_ringbuffer_linear_read_setup(&rb, &size); /** * 用于DMA完成,增加读指针 * 返回实际增加长度 */ size = chry_ringbuffer_linear_read_done(&rb, 512); /** * 用于启动DMA,获取写入起始内存地址和最大线性可写入长度 */ pdata = chry_ringbuffer_linear_write_setup(&rb, &size); /** * 用于DMA完成,增加写指针 * 返回实际增加长度 */ size = chry_ringbuffer_linear_write_done(&rb, 512); ```