一个RINGBUFFER的C代码实现

编程入门 行业动态 更新时间:2024-10-25 04:16:08

一个RINGBUFFER的C<a href=https://www.elefans.com/category/jswz/34/1771412.html style=代码实现"/>

一个RINGBUFFER的C代码实现

头文件

#ifndef __RING_BUFFER__
#define __RING_BUFFER__
#include <stdint.h>
#include <stddef.h>
#include <pthread.h>
#include <unistd.h>struct ringbuffer
{uint8_t *buffer_ptr;uint16_t read_mirror : 1;uint16_t read_index : 15;uint16_t write_mirror : 1;uint16_t write_index : 15;int16_t buffer_size;pthread_mutex_t mutex_lock;
};enum ringbuffer_state
{RINGBUFFER_EMPTY,RINGBUFFER_FULL,RINGBUFFER_HALFFULL,RINGBUFFER_INVALID,
};void ringbuffer_init(struct ringbuffer *rb, uint8_t *pool, int16_t size);
void ringbuffer_reset(struct ringbuffer *rb);
int16_t ringbuffer_put(struct ringbuffer *rb, const uint8_t *ptr, int16_t length);
int16_t ringbuffer_get(struct ringbuffer *rb, uint8_t *ptr, int16_t length);
int16_t ringbuffer_data_len(struct ringbuffer *rb);struct ringbuffer* ringbuffer_create(int16_t length);
void ringbuffer_destroy(struct ringbuffer *rb);static inline int16_t ringbuffer_get_size(struct ringbuffer *rb)
{return rb->buffer_size;    
}#define ringbuffer_space_len(rb) ((rb)->buffer_size - ringbuffer_data_len(rb))#endif

实现源码:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ringbuffer.h"void ringbuffer_init(struct ringbuffer *rb, uint8_t *pool, int16_t size)
{if(rb == NULL){return;}rb->read_mirror = rb->read_index = 0;rb->write_mirror = rb->write_index = 0;rb->buffer_ptr = pool;rb->buffer_size = size;pthread_mutex_init(&rb->mutex_lock,NULL);return;
}void ringbuffer_reset(struct ringbuffer *rb)
{if(rb == NULL){return;}rb->read_mirror = 0;rb->read_index = 0;rb->write_mirror = 0;rb->write_index = 0;return;
}int16_t ringbuffer_put(struct ringbuffer *rb, const uint8_t *ptr, int16_t length)
{int16_t size; if(rb == NULL || length == 0){return 0;}pthread_mutex_lock(&rb->mutex_lock);size = ringbuffer_space_len(rb);pthread_mutex_unlock(&rb->mutex_lock);if(size == 0)return 0;if (size < length){length = size;}if (rb->buffer_size - rb->write_index > length){memcpy(&rb->buffer_ptr[rb->write_index], ptr, length);rb->write_index += length; return length;}memcpy(&rb->buffer_ptr[rb->write_index],&ptr[0],rb->buffer_size - rb->write_index);memcpy(&rb->buffer_ptr[0],&ptr[rb->buffer_size - rb->write_index],length - (rb->buffer_size - rb->write_index));pthread_mutex_lock(&rb->mutex_lock);rb->write_mirror = ~rb->write_mirror;rb->write_index = length - (rb->buffer_size - rb->write_index);pthread_mutex_unlock(&rb->mutex_lock);return length;
}int16_t ringbuffer_get(struct ringbuffer *rb, uint8_t *ptr, int16_t length)
{if(rb == NULL || length == 0){return 0;}int16_t size; pthread_mutex_lock(&rb->mutex_lock);size = ringbuffer_data_len(rb);pthread_mutex_unlock(&rb->mutex_lock);if (size == 0) return 0;if (size < length){length = size;}if (rb->buffer_size - rb->read_index > length){memcpy(ptr, &rb->buffer_ptr[rb->read_index], length);rb->read_index += length;return length;}memcpy(&ptr[0],&rb->buffer_ptr[rb->read_index],rb->buffer_size - rb->read_index);memcpy(&ptr[rb->buffer_size - rb->read_index], &rb->buffer_ptr[0], length - (rb->buffer_size - rb->read_index));pthread_mutex_lock(&rb->mutex_lock);rb->read_mirror = ~rb->read_mirror; rb->read_index = length - (rb->buffer_size - rb->read_index);pthread_mutex_unlock(&rb->mutex_lock);return length;
}enum ringbuffer_state ringbuffer_status(struct ringbuffer *rb) 
{if (rb->read_index == rb->write_index){if (rb->read_mirror == rb->write_mirror){return RINGBUFFER_EMPTY;}else{return RINGBUFFER_FULL;}}return RINGBUFFER_HALFFULL;
}int16_t ringbuffer_data_len(struct ringbuffer *rb)
{switch (ringbuffer_status(rb)) {case RINGBUFFER_EMPTY:return 0;case RINGBUFFER_FULL:return rb->buffer_size; case RINGBUFFER_HALFFULL:default:if (rb->write_index > rb->read_index)return rb->write_index - rb->read_index;elsereturn rb->buffer_size - (rb->read_index - rb->write_index); }
}

测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include "ringbuffer.h"pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;struct ringbuffer *rb;
void *writer_thread(void *args)
{uint8_t w = 0;while(1){/*pthread_mutex_lock(&mutex);*/if(ringbuffer_put(rb, &w, 1) == 1)w ++;/*pthread_mutex_unlock(&mutex);*/}return NULL;
}void *reader_thread(void *args)
{uint8_t r;while(1){/*pthread_mutex_lock(&mutex);*/if (ringbuffer_get(rb, &r, 1) == 1)printf("---%x---\n", r);/*pthread_mutex_unlock(&mutex);*/}return NULL;
}int main(void)
{unsigned int rc;#if 1uint8_t *buffer = (uint8_t *)malloc(1024 + sizeof(struct ringbuffer) + 16);if(buffer == NULL) return -1;if((unsigned long)buffer & 7 != 0){printf("%s line %d not aligned.\n", __func__, __LINE__);return -1;}rb=(struct ringbuffer *)buffer;if(rb == NULL) return -1;ringbuffer_init(rb, buffer + sizeof(struct ringbuffer), 1024);printf("buffer = %p, sizeof(rb) = %ld.\n", buffer, sizeof(struct ringbuffer));#elsestatic struct ringbuffer rbb;uint8_t *buffer = (uint8_t *)malloc(1024);if(buffer == NULL) return -1;rb = &rbb;memset(rb, 0x00,sizeof(struct ringbuffer));memset(buffer, 0x00,1024);ringbuffer_init(rb, buffer, 1024);
#endifpthread_t writer;rc = pthread_create(&writer, NULL, writer_thread, NULL);if (rc){printf("ERROR; return code is %d\n", rc);return EXIT_FAILURE;}pthread_t reader;rc = pthread_create(&reader, NULL, reader_thread, NULL);if (rc){printf("ERROR; return code is %d\n", rc);return EXIT_FAILURE;}pthread_join(reader, NULL);pthread_join(writer, NULL);return EXIT_SUCCESS;
}

Makefile

all:gcc main.c ringbuffer.c -o main -lpthread

测试:

另外,Linux内核也有一个不错的实现,参考:

./linux-5.4.99/drivers/media/dvb-core/dvb_ringbuffer.c

严蔚敏数据结构中的循环队列实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAXQSIZE 100typedef struct {unsigned long *base;int front;int rear;
} user_queue_t;static user_queue_t uqueue;int init_queue(user_queue_t *q)
{q->base = (unsigned long *)malloc(MAXQSIZE * sizeof(unsigned long));if (!q->base) {printf("%s line %d, malloc queue failure.\n",__func__, __LINE__);exit(-1);}memset(q->base, 0x00, sizeof(unsigned long) * MAXQSIZE);q->front = q->rear = 0;return 0;
}int queue_length(user_queue_t *q)
{return (q->rear - q->front + MAXQSIZE) % MAXQSIZE;
}int enqueue(user_queue_t *q, unsigned long e)
{if ((q->rear + 1) % MAXQSIZE == q->front) {printf("%s line %d, queue full.\n",__func__, __LINE__);return -1;}q->base[q->rear] = e;q->rear = (q->rear + 1) % MAXQSIZE;return 0;
}unsigned long dequeue(user_queue_t *q)
{unsigned long e;if (q->front == q->rear) {printf("%s line %d, queue is null.\n",__func__, __LINE__);return -1;}e = q->base[q->front];q->front = (q->front + 1) % MAXQSIZE;return e;
}int main(void)
{int i;unsigned long e;init_queue(&uqueue);printf("%s line %d, queue_length %d.\n", __func__, __LINE__, queue_length(&uqueue));enqueue(&uqueue, 100);printf("%s line %d, queue_length %d.\n", __func__, __LINE__, queue_length(&uqueue));e = dequeue(&uqueue);printf("%s line %d, queue_length %d, e %ld.\n", __func__, __LINE__, queue_length(&uqueue), e);for (i = 0; i < MAXQSIZE; i ++) {enqueue(&uqueue, i);printf("%s line %d, queue_length %d.\n", __func__, __LINE__, queue_length(&uqueue));}for (i = 0; i < MAXQSIZE; i ++) {e = dequeue(&uqueue);printf("%s line %d, queue_length %d, e %ld.\n", __func__, __LINE__, queue_length(&uqueue), e);}return 0;
}

结束!

更多推荐

一个RINGBUFFER的C代码实现

本文发布于:2024-02-25 02:48:03,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1697533.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:代码   RINGBUFFER

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!