21 #ifndef SV_RINGBUFFER_H 22 #define SV_RINGBUFFER_H 24 #include <sys/types.h> 28 #include <bqvec/Barrier.h> 29 #include <bqvec/VectorOps.h> 35 #ifdef DEBUG_RINGBUFFER 44 template <
typename T,
int N = 1>
99 int read(T *destination,
int n,
int R = 0);
107 int readAdding(T *destination,
int n,
int R = 0);
125 int peek(T *destination,
int n,
int R = 0)
const;
141 int skip(
int n,
int R = 0);
148 int write(
const T *source,
int n);
161 std::vector<T, breakfastquay::StlAllocator<T>>
m_buffer;
167 template <
typename T,
int N>
174 #ifdef DEBUG_RINGBUFFER 175 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::RingBuffer(" << n <<
")" << std::endl;
179 template <
typename T,
int N>
182 #ifdef DEBUG_RINGBUFFER 183 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::~RingBuffer" << std::endl;
187 template <
typename T,
int N>
191 #ifdef DEBUG_RINGBUFFER 192 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::getSize(): " <<
m_size-1 << std::endl;
198 template <
typename T,
int N>
202 #ifdef DEBUG_RINGBUFFER 203 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::resized(" << newSize <<
")" << std::endl;
213 newBuffer->
write(&value, 1);
220 template <
typename T,
int N>
224 #ifdef DEBUG_RINGBUFFER 225 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::reset" << std::endl;
229 for (
int i = 0; i < N; ++i) {
234 template <
typename T,
int N>
242 if (writer > reader) space = writer - reader;
245 #ifdef DEBUG_RINGBUFFER 246 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::getReadSpace(" << R <<
"): " << space << std::endl;
252 template <
typename T,
int N>
257 for (
int i = 0; i < N; ++i) {
259 if (i == 0 || here < space) space = here;
262 #ifdef DEBUG_RINGBUFFER 265 std::cerr <<
"RingBuffer: write space " << space <<
", read space " 266 << rs <<
", total " << (space + rs) <<
", m_size " <<
m_size << std::endl;
267 std::cerr <<
"RingBuffer: reader " << rp <<
", writer " <<
m_writer << std::endl;
270 #ifdef DEBUG_RINGBUFFER 271 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::getWriteSpace(): " << space << std::endl;
277 template <
typename T,
int N>
281 #ifdef DEBUG_RINGBUFFER 282 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::read(dest, " << n <<
", " << R <<
")" << std::endl;
287 #ifdef DEBUG_RINGBUFFER 288 std::cerr <<
"WARNING: Only " << available <<
" samples available" 291 breakfastquay::v_zero(destination + available, n - available);
294 if (n == 0)
return n;
298 breakfastquay::v_copy(destination,
m_buffer.data() + m_readers[R], n);
300 breakfastquay::v_copy(destination,
m_buffer.data() + m_readers[R], here);
301 breakfastquay::v_copy(destination + here,
m_buffer.data(), n - here);
305 m_readers[R] = (m_readers[R] + n) %
m_size;
307 #ifdef DEBUG_RINGBUFFER 308 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::read: read " << n <<
", reader now " << m_readers[R] << std::endl;
314 template <
typename T,
int N>
318 #ifdef DEBUG_RINGBUFFER 319 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::readAdding(dest, " << n <<
", " << R <<
")" << std::endl;
324 #ifdef DEBUG_RINGBUFFER 325 std::cerr <<
"WARNING: Only " << available <<
" samples available" 330 if (n == 0)
return n;
335 for (
int i = 0; i < n; ++i) {
336 destination[i] += (
m_buffer.data() + m_readers[R])[i];
339 for (
int i = 0; i < here; ++i) {
340 destination[i] += (
m_buffer.data() + m_readers[R])[i];
342 for (
int i = 0; i < (n - here); ++i) {
343 destination[i + here] +=
m_buffer[i];
348 m_readers[R] = (m_readers[R] + n) %
m_size;
352 template <
typename T,
int N>
356 #ifdef DEBUG_RINGBUFFER 357 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::readOne(" << R <<
")" << std::endl;
361 #ifdef DEBUG_RINGBUFFER 362 std::cerr <<
"WARNING: No sample available" 369 if (++m_readers[R] ==
m_size) m_readers[R] = 0;
373 template <
typename T,
int N>
377 #ifdef DEBUG_RINGBUFFER 378 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::peek(dest, " << n <<
", " << R <<
")" << std::endl;
383 #ifdef DEBUG_RINGBUFFER 384 std::cerr <<
"WARNING: Only " << available <<
" samples available" 387 breakfastquay::v_zero(destination + available, n - available);
390 if (n == 0)
return n;
394 breakfastquay::v_copy(destination,
m_buffer.data() + m_readers[R], n);
396 breakfastquay::v_copy(destination,
m_buffer.data() + m_readers[R], here);
397 breakfastquay::v_copy(destination + here,
m_buffer.data(), n - here);
400 #ifdef DEBUG_RINGBUFFER 401 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::peek: read " << n << std::endl;
407 template <
typename T,
int N>
411 #ifdef DEBUG_RINGBUFFER 412 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::peek(" << R <<
")" << std::endl;
416 #ifdef DEBUG_RINGBUFFER 417 std::cerr <<
"WARNING: No sample available" 426 template <
typename T,
int N>
430 #ifdef DEBUG_RINGBUFFER 431 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::skip(" << n <<
", " << R <<
")" << std::endl;
436 #ifdef DEBUG_RINGBUFFER 437 std::cerr <<
"WARNING: Only " << available <<
" samples available" 442 if (n == 0)
return n;
447 template <
typename T,
int N>
451 #ifdef DEBUG_RINGBUFFER 452 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::write(" << n <<
")" << std::endl;
457 #ifdef DEBUG_RINGBUFFER 458 std::cerr <<
"WARNING: Only room for " << available <<
" samples" 463 if (n == 0)
return n;
470 breakfastquay::v_copy(
m_buffer.data(), source + here, n - here);
474 m_writer = (m_writer + n) %
m_size;
476 #ifdef DEBUG_RINGBUFFER 477 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::write: wrote " << n <<
", writer now " << m_writer << std::endl;
483 template <
typename T,
int N>
487 #ifdef DEBUG_RINGBUFFER 488 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::zero(" << n <<
")" << std::endl;
493 #ifdef DEBUG_RINGBUFFER 494 std::cerr <<
"WARNING: Only room for " << available <<
" samples" 499 if (n == 0)
return n;
506 breakfastquay::v_zero(
m_buffer.data(), n - here);
510 m_writer = (m_writer + n) %
m_size;
514 #endif // _RINGBUFFER_H_ T peekOne(int R=0) const
Read one sample from the buffer, if available, without advancing the read pointer – i...
std::vector< int > m_readers
int getSize() const
Return the total capacity of the ring buffer in samples.
std::vector< T, breakfastquay::StlAllocator< T > > m_buffer
RingBuffer & operator=(const RingBuffer &)=default
T readOne(int R=0)
Read one sample from the buffer, for reader R.
void reset()
Reset read and write pointers, thus emptying the buffer.
int read(T *destination, int n, int R=0)
Read n samples from the buffer, for reader R.
RingBuffer< T, N > resized(int newSize) const
Return a new ring buffer of the given size, containing the same data as this one as perceived by read...
int peek(T *destination, int n, int R=0) const
Read n samples from the buffer, if available, for reader R, without advancing the read pointer – i...
int write(const T *source, int n)
Write n samples to the buffer.
int getReadSpace(int R=0) const
Return the amount of data available for reading by reader R, in samples.
RingBuffer(int n)
Create a ring buffer with room to write n samples.
int getWriteSpace() const
Return the amount of space available for writing, in samples.
RingBuffer implements a lock-free ring buffer for one writer and N readers, that is to be used to sto...
int skip(int n, int R=0)
Pretend to read n samples from the buffer, for reader R, without actually returning them (i...
int readAdding(T *destination, int n, int R=0)
Read n samples from the buffer, for reader R, adding them to the destination.
int zero(int n)
Write n zero-value samples to the buffer.