Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you implement a circular buffer in C?

I have a need for a fixed-size (selectable at run-time when creating it, not compile-time) circular buffer which can hold objects of any type and it needs to be very high performance. I don't think there will be resource contention issues since, although it's in a multi-tasking embedded environment, it's a co-operative one so the tasks themselves can manage that.

My initial thought was to store a simple struct in the buffer which would contain the type (simple enum/define) and a void pointer to the payload but I want this to be as fast as possible so I'm open to suggestions that involve bypassing the heap.

Actually I'm happy to bypass any of the standard library for raw speed - from what I've seen of the code, it's not heavily optimized for the CPU : it looks like they just compiled C code for things like strcpy() and such, there's no hand-coded assembly.

Any code or ideas would be greatly appreciated. The operations required are:

  • create a buffer with specific size.
  • put at the tail.
  • get from the head.
  • return the count.
  • delete a buffer.
like image 405
paxdiablo Avatar asked May 06 '09 01:05

paxdiablo


People also ask

How do you use a circular buffer?

Circular buffers use FIFO (first in, first out) logic. In the example, 1 & 2 were the first to enter the circular buffer, they are the first to be removed, leaving 3 inside of the buffer. Alternatively, the routines that manage the buffer could prevent overwriting the data and return an error or raise an exception.

What is a ring buffer in C?

Circular buffers (also known as ring buffers) are fixed-size buffers that work as if the memory is contiguous & circular in nature. As memory is generated and consumed, data does not need to be reshuffled – rather, the head/tail pointers are adjusted. When data is added, the head pointer advances.

How is a buffer implemented?

Buffers can be implemented in a fixed memory location in hardware—or by using a virtual data buffer in software, pointing at a location in the physical memory. In all cases, the data stored in a data buffer are stored on a physical storage medium.

What is circular buffer in operating system?

A circular buffer is a memory allocation scheme where memory is reused (reclaimed) when an index, incremented modulo the buffer size, writes over a previously used location. A circular buffer makes a bounded queue when separate indices are used for inserting and removing data.


1 Answers

The simplest solution would be to keep track of the item size and the number of items, and then create a buffer of the appropriate number of bytes:

typedef struct circular_buffer {     void *buffer;     // data buffer     void *buffer_end; // end of data buffer     size_t capacity;  // maximum number of items in the buffer     size_t count;     // number of items in the buffer     size_t sz;        // size of each item in the buffer     void *head;       // pointer to head     void *tail;       // pointer to tail } circular_buffer;  void cb_init(circular_buffer *cb, size_t capacity, size_t sz) {     cb->buffer = malloc(capacity * sz);     if(cb->buffer == NULL)         // handle error     cb->buffer_end = (char *)cb->buffer + capacity * sz;     cb->capacity = capacity;     cb->count = 0;     cb->sz = sz;     cb->head = cb->buffer;     cb->tail = cb->buffer; }  void cb_free(circular_buffer *cb) {     free(cb->buffer);     // clear out other fields too, just to be safe }  void cb_push_back(circular_buffer *cb, const void *item) {     if(cb->count == cb->capacity){         // handle error     }     memcpy(cb->head, item, cb->sz);     cb->head = (char*)cb->head + cb->sz;     if(cb->head == cb->buffer_end)         cb->head = cb->buffer;     cb->count++; }  void cb_pop_front(circular_buffer *cb, void *item) {     if(cb->count == 0){         // handle error     }     memcpy(item, cb->tail, cb->sz);     cb->tail = (char*)cb->tail + cb->sz;     if(cb->tail == cb->buffer_end)         cb->tail = cb->buffer;     cb->count--; } 
like image 136
Adam Rosenfield Avatar answered Sep 28 '22 06:09

Adam Rosenfield