Skip to content

Instantly share code, notes, and snippets.

@hosaka
Created August 17, 2015 12:40
Show Gist options
  • Save hosaka/985abd49cd737479a5fc to your computer and use it in GitHub Desktop.
Save hosaka/985abd49cd737479a5fc to your computer and use it in GitHub Desktop.
Ring buffer / circular queue example in C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ring_buf.h"
/* Ring bufffer / Circular buffer / Circular Queue implementation
* The queue grows from the head and shrinks from the tail
*/
int main(int argc, char const *argv[])
{
// buffer structure
rbuf_t buffer;
// init buffer
ringbuf_init(&buffer);
// pulling from an empty buffer will not work
int elem = ringbuf_get(&buffer);
printf("buffer is %s\n", RBUF_EMPTY == elem ? "empty" : "not empty");
// fill up the buffer
for (int i = 0; i < RBUF_SIZE; ++i)
{
ringbuf_put(&buffer, i);
}
// show buffer
ringbuf_print(&buffer);
printf("first elem to go out: %d\n", ringbuf_peek(&buffer));
// buffer is full, trying to insert will not work
ringbuf_put(&buffer, 42);
// however if we delete some from the buffer
(void)ringbuf_get(&buffer);
// we can insert again
ringbuf_put(&buffer, 42);
ringbuf_print(&buffer);
// we can reset buffer counts or clear the contents completely
ringbuf_flush(&buffer, RBUF_CLEAR);
return EXIT_SUCCESS;
}
void ringbuf_init(rbuf_t* _this)
{
// clear the _thisfer and init the values
// and sets head = tail in one go
memset( _this, 0, sizeof(*_this) );
}
bool ringbuf_empty(rbuf_t* _this)
{
// test if the queue is empty
// 0 returns true
// nonzero false
return (0 == _this->count);
}
bool ringbuf_full(rbuf_t* _this)
{
// full when no of elements exceed the max size
return (_this->count >= RBUF_SIZE);
}
int ringbuf_get(rbuf_t* _this)
{
int item;
if (_this->count > 0)
{
// get item element
item = _this->buf[_this->tail];
// advance the tail
_this->tail = ringbuf_adv(_this->tail, RBUF_SIZE);
// reduce the total count
--_this->count;
}
else {
// the queue is empty
item = RBUF_EMPTY;
}
return item;
}
void ringbuf_put(rbuf_t* _this, const unsigned char item)
{
if (_this->count < RBUF_SIZE)
{
// set the item at head position
_this->buf[_this->head] = item;
// advance the head
_this->head = ringbuf_adv(_this->head, RBUF_SIZE);
// increase the total count
++_this->count;
}
}
int ringbuf_peek(rbuf_t* _this)
{
if (_this->count != 0)
{
return _this->buf[_this->tail];
}
}
void ringbuf_print(rbuf_t* _this)
{
for (int i = 0; i < RBUF_SIZE; i++)
{
printf("%d ", _this->buf[i]);
}
printf("\n");
}
void ringbuf_flush(rbuf_t* _this, rbuf_opt_e clear)
{
_this->count = 0;
_this->head = 0;
_this->tail = 0;
// optionally clear
if (RBUF_CLEAR == clear)
{
memset(_this->buf, 0, sizeof(_this->buf));
}
}
static unsigned int ringbuf_adv(const unsigned int value, const unsigned int max)
{
unsigned int index = value + 1;
if (index >= max)
{
index = 0;
}
return index;
}
#ifndef RING_BUF_H
#define RING_BUF_H
#include <stdbool.h>
// maximum buffer size
#define RBUF_SIZE 8
// buffer structure
typedef struct ring_buf_s
{
unsigned char buf[RBUF_SIZE];
int head; // new data is written at this position in the buffer
int tail; // data is read from this position in the buffer
int count; // total number of elements in the queue <= RBUF_SIZE
} rbuf_t;
// ring buffer options
typedef enum
{
RBUF_CLEAR,
RBUF_NO_CLEAR
} rbuf_opt_e;
// buffer messages
typedef enum
{
RBUF_EMPTY = -1,
RBUF_FULL
} rbuf_msg_e;
// API
// initialise the queue
void ringbuf_init(rbuf_t* _this);
// determine if the queue is empty
bool ringbuf_empty(rbuf_t* _this);
// determine if the queue is full
bool ringbuf_full(rbuf_t* _this);
// fetch a byte from the queue at tail
int ringbuf_get(rbuf_t* _this);
// insert a byte to the queue at head
void ringbuf_put(rbuf_t* _this, const unsigned char item);
// peek at the first element in the queue
int ringbuf_peek(rbuf_t* _this);
// flush the queue and clear the buffer
void ringbuf_flush(rbuf_t* _this, rbuf_opt_e clear);
// print the contents
void ringbuf_print(rbuf_t* _this);
// advance the ring buffer index
static unsigned int ringbuf_adv (const unsigned int value, const unsigned int max_val);
#endif
@chunyilu
Copy link

Hi hosaka,

thanks for your ring buf code, I download it and compile

but there are some warnings happen while compile

  1. ringbuf_peek() return type is int, but there is no else condition to return other number

  2. do not need static keyword for ringbuf_adv(), and the parameter max is different with function prototype max_val

@asmamaw
Copy link

asmamaw commented Apr 23, 2018

for the first question declare a type int variable and make the function to return it
like this int buff = _this->buf[_this->tail];
return buff ;
#no brace for if

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment