A circular buffer, also known as cyclic buffer or ring buffer is a special data structure that uses a single, fixed-size buffer as if it were connected end-to-end. That is, if you reach writing to the last available slot in the buffer, the next slot to write into is the first slot of the buffer. You can find the gereric version here
The following code is a sample implementation of that structure. You can freely use them if you need to. The code standard I am trying to follow is Google's C++ Style.
The header file:
circular_buffer.hpp
The following code is a sample implementation of that structure. You can freely use them if you need to. The code standard I am trying to follow is Google's C++ Style.
The header file:
circular_buffer.hpp
#ifndef MCP_CIRCULAR_BUFFER_H_ #define MCP_CIRCULAR_BUFFER_H_ namespace base { // This is a fixed-size, circular buffer of integer. // The class is not thread-safe, class CircularBuffer { public: // Creates a buffer with 'slots' slots. explicit CircularBuffer(int slots); // Destructor. ~CircularBuffer(); // Writes 'value' to the next available slot. It may overwrite // values that were not yet read out of the buffer. void write(int value); // Returns the next value available for reading, in the order they // were written, and marks slot as read. If the buffer is empty returns -1. int read(); // Removes all the elements from the buffer. void clear(); private: //array of integers int* data_; // the size of the buffer int num_of_slots_; //index to read the next integer from buffer int read_index_; //index to write a new integer to buffer int write_index_; // Non-copyable, non-assignable. CircularBuffer(CircularBuffer&); CircularBuffer& operator=(const CircularBuffer&); }; } // namespace base #endif // MCP_CIRCULAR_BUFFER_H_
circular_buffer.cpp
#include "circular_buffer.hpp" namespace base { CircularBuffer::CircularBuffer(int slots) { if (slots <= 0) { num_of_slots_ = 10; /*pre-assigned value */ } else { num_of_slots_ = slots; } clear(); } CircularBuffer::~CircularBuffer() { delete[] data_; } void CircularBuffer::write(int value) { data_[write_index_] = value; if (read_index_ == -1) { //if buffer is empty, set the read index to the //current write index. because that will be the first //slot to be read later. read_index_ = write_index_; } write_index_ = (write_index_ + 1) % num_of_slots_; } int CircularBuffer::read() { if (read_index_ == -1) { // buffer empty return -1; } int ret_val = data_[read_index_]; read_index_ = (read_index_ + 1) % num_of_slots_; if (read_index_ == write_index_) { /*all available data is read, now buffer is empty*/ read_index_ = -1; } return ret_val; } void CircularBuffer::clear() { read_index_ = -1; /* buffer empty */ write_index_ = 0; /* first time writing to that buffer*/ delete [] data_; data_ = new int[num_of_slots_]; /* allocate space for buffer */ } } // namespace base