File ringbuffer.h¶
File List > external-docs > libDaisy > src > util > ringbuffer.h
Go to the documentation of this file
Source Code¶
#pragma once
#ifndef DSY_RINGBUFFER_H
#define DSY_RINGBUFFER_H
#include <algorithm>
namespace daisy
{
template <typename T, size_t size>
class RingBuffer
{
public:
RingBuffer() {}
inline void Init() { read_ptr_ = write_ptr_ = 0; }
inline size_t capacity() const { return size; }
inline size_t writable() const
{
return (read_ptr_ - write_ptr_ - 1) % size;
}
inline size_t readable() const { return (write_ptr_ - read_ptr_) % size; }
inline bool isEmpty() const { return write_ptr_ == read_ptr_; }
inline void Write(T v)
{
while(!writable())
;
Overwrite(v);
}
inline void Overwrite(T v)
{
size_t w = write_ptr_;
buffer_[w] = v;
write_ptr_ = (w + 1) % size;
}
inline T Read()
{
while(!readable())
;
return ImmediateRead();
}
inline T ImmediateRead()
{
size_t r = read_ptr_;
T result = buffer_[r];
read_ptr_ = (r + 1) % size;
return result;
}
inline void Flush() { write_ptr_ = read_ptr_; }
inline void Swallow(size_t n)
{
if(writable() >= n)
{
return;
}
read_ptr_ = (write_ptr_ + 1 + n) % size;
}
inline void ImmediateRead(T* destination, size_t num_elements)
{
size_t r = read_ptr_;
size_t read = num_elements;
if(r + read > size)
{
read = size - r;
}
std::copy(&buffer_[r], &buffer_[r + read], destination);
if(read != num_elements)
{
std::copy(
&buffer_[0], &buffer_[num_elements - read], destination + read);
}
read_ptr_ = (r + num_elements) % size;
}
inline void Overwrite(const T* source, size_t num_elements)
{
size_t w = write_ptr_;
size_t written = num_elements;
if(w + written > size)
{
written = size - w;
}
std::copy(source, source + written, &buffer_[w]);
if(written != num_elements)
{
std::copy(source + written, source + num_elements, &buffer_[0]);
}
write_ptr_ = (w + num_elements) % size;
}
inline void Advance(size_t num_elements)
{
size_t free;
free = this->writable();
num_elements = num_elements < free ? num_elements : free;
write_ptr_ = write_ptr_ + num_elements;
if(write_ptr_ > size)
write_ptr_ = write_ptr_ - size;
}
inline T* GetMutableBuffer() { return buffer_; }
private:
T buffer_[size];
volatile size_t read_ptr_;
volatile size_t write_ptr_;
};
template <typename T>
class RingBuffer<T, 0>
{
public:
RingBuffer() {}
inline void Init() {}
inline size_t capacity() const { return 0; }
inline size_t writable() const { return 0; }
inline size_t readable() const { return 0; }
inline void Write(T v) { (void)(v); }
inline void Overwrite(T v)
{
(void)(v);
}
inline T Read() { return T(0); }
inline T ImmediateRead() { return T(0); }
inline void Flush() {}
inline void ImmediateRead(T* destination, size_t num_elements)
{
(void)(destination);
(void)(num_elements);
}
inline void Overwrite(const T* source, size_t num_elements)
{
(void)(source);
(void)(num_elements);
}
private:
};
} // namespace daisy
#endif