Created
December 27, 2018 10:56
-
-
Save amakukha/2ee8930a2ad4979fdab64d0c666bacce to your computer and use it in GitHub Desktop.
Circular buffer in C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _RING_BUFFER_ | |
#define _RING_BUFFER_ | |
// Source: https://embeddedartistry.com/blog/2017/4/6/circular-buffers-in-cc | |
#include <memory> | |
#include <mutex> | |
template <class T> | |
class RingBuffer { | |
public: | |
explicit RingBuffer(size_t size) : | |
buf_(std::unique_ptr<T[]>(new T[size])), | |
max_size_(size) {}; | |
void put(T item); | |
T get(); | |
void reset(); | |
bool empty() const; | |
bool full() const; | |
size_t capacity() const; | |
size_t size() const; | |
private: | |
std::mutex mutex_; | |
std::unique_ptr<T[]> buf_; | |
size_t head_ = 0; | |
size_t tail_ = 0; | |
const size_t max_size_; | |
bool full_ = 0; | |
}; | |
template<class T> | |
void RingBuffer<T>::reset() { | |
std::lock_guard<std::mutex> lock(mutex_); | |
head_ = tail_; | |
full_ = false; | |
} | |
template<class T> | |
bool RingBuffer<T>::empty() const { | |
//if head and tail are equal, we are empty | |
return (!full_ && (head_ == tail_)); | |
} | |
template<class T> | |
bool RingBuffer<T>::full() const { | |
//If tail is ahead the head by 1, we are full | |
return full_; | |
} | |
template<class T> | |
size_t RingBuffer<T>::capacity() const { | |
return max_size_; | |
} | |
template<class T> | |
size_t RingBuffer<T>::size() const { | |
size_t size = max_size_; | |
if(!full_) { | |
if(head_ >= tail_) | |
size = head_ - tail_; | |
else | |
size = max_size_ + head_ - tail_; | |
} | |
return size; | |
} | |
template<class T> | |
void RingBuffer<T>::put(T item) { | |
std::lock_guard<std::mutex> lock(mutex_); | |
buf_[head_] = item; | |
// TODO: stop writing to buffer if full | |
if(full_) | |
tail_ = (tail_ + 1) % max_size_; | |
head_ = (head_ + 1) % max_size_; | |
full_ = head_ == tail_; | |
} | |
template<class T> | |
T RingBuffer<T>::get() { | |
std::lock_guard<std::mutex> lock(mutex_); | |
if(empty()) return T(); | |
//Read data and advance the tail (we now have a free space) | |
auto val = buf_[tail_]; | |
full_ = false; | |
tail_ = (tail_ + 1) % max_size_; | |
return val; | |
} | |
#endif // _RING_BUFFER_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment