21 #ifndef _RINGBUFFER_H_ 22 #define _RINGBUFFER_H_ 24 #include <sys/types.h> 32 #ifdef DEBUG_RINGBUFFER 45 template <
typename T,
int N = 1>
107 int read(T *destination,
int n,
int R = 0);
115 int readAdding(T *destination,
int n,
int R = 0);
133 int peek(T *destination,
int n,
int R = 0)
const;
149 int skip(
int n,
int R = 0);
156 int write(
const T *source,
int n);
178 template <
typename T,
int N>
180 m_buffer(new T[n + 1]),
183 m_readers(new int[N]),
186 #ifdef DEBUG_RINGBUFFER 187 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::RingBuffer(" << n <<
")" << std::endl;
200 for (
int i = 0; i < N; ++i)
m_readers[i] = 0;
203 template <
typename T,
int N>
206 #ifdef DEBUG_RINGBUFFER 207 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::~RingBuffer" << std::endl;
213 MUNLOCK((
void *)m_buffer, m_size *
sizeof(T));
218 template <
typename T,
int N>
222 #ifdef DEBUG_RINGBUFFER 223 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::getSize(): " << m_size-1 << std::endl;
229 template <
typename T,
int N>
233 #ifdef DEBUG_RINGBUFFER 234 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::resized(" << newSize <<
")" << std::endl;
240 int r = m_readers[0];
243 T value = m_buffer[r];
244 newBuffer->
write(&value, 1);
245 if (++r == m_size) r = 0;
251 template <
typename T,
int N>
255 if (
MLOCK((
void *)m_buffer, m_size *
sizeof(T)))
return false;
260 template <
typename T,
int N>
264 #ifdef DEBUG_RINGBUFFER 265 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::reset" << std::endl;
269 for (
int i = 0; i < N; ++i) m_readers[i] = 0;
272 template <
typename T,
int N>
276 int writer = m_writer;
277 int reader = m_readers[R];
280 if (writer > reader) space = writer - reader;
281 else space = ((writer + m_size) - reader) % m_size;
283 #ifdef DEBUG_RINGBUFFER 284 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::getReadSpace(" << R <<
"): " << space << std::endl;
290 template <
typename T,
int N>
295 for (
int i = 0; i < N; ++i) {
296 int here = (m_readers[i] + m_size - m_writer - 1) % m_size;
297 if (i == 0 || here < space) space = here;
300 #ifdef DEBUG_RINGBUFFER 301 int rs(getReadSpace()), rp(m_readers[0]);
303 std::cerr <<
"RingBuffer: write space " << space <<
", read space " 304 << rs <<
", total " << (space + rs) <<
", m_size " << m_size << std::endl;
305 std::cerr <<
"RingBuffer: reader " << rp <<
", writer " << m_writer << std::endl;
308 #ifdef DEBUG_RINGBUFFER 309 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::getWriteSpace(): " << space << std::endl;
315 template <
typename T,
int N>
319 #ifdef DEBUG_RINGBUFFER 320 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::read(dest, " << n <<
", " << R <<
")" << std::endl;
323 int available = getReadSpace(R);
325 #ifdef DEBUG_RINGBUFFER 326 std::cerr <<
"WARNING: Only " << available <<
" samples available" 329 memset(destination + available, 0, (n - available) *
sizeof(T));
332 if (n == 0)
return n;
334 int here = m_size - m_readers[R];
336 memcpy(destination, m_buffer + m_readers[R], n *
sizeof(T));
338 memcpy(destination, m_buffer + m_readers[R], here *
sizeof(T));
339 memcpy(destination + here, m_buffer, (n - here) *
sizeof(T));
343 m_readers[R] = (m_readers[R] + n) % m_size;
345 #ifdef DEBUG_RINGBUFFER 346 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::read: read " << n <<
", reader now " << m_readers[R] << std::endl;
352 template <
typename T,
int N>
356 #ifdef DEBUG_RINGBUFFER 357 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::readAdding(dest, " << n <<
", " << R <<
")" << std::endl;
360 int available = getReadSpace(R);
362 #ifdef DEBUG_RINGBUFFER 363 std::cerr <<
"WARNING: Only " << available <<
" samples available" 368 if (n == 0)
return n;
370 int here = m_size - m_readers[R];
373 for (
int i = 0; i < n; ++i) {
374 destination[i] += (m_buffer + m_readers[R])[i];
377 for (
int i = 0; i < here; ++i) {
378 destination[i] += (m_buffer + m_readers[R])[i];
380 for (
int i = 0; i < (n - here); ++i) {
381 destination[i + here] += m_buffer[i];
386 m_readers[R] = (m_readers[R] + n) % m_size;
390 template <
typename T,
int N>
394 #ifdef DEBUG_RINGBUFFER 395 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::readOne(" << R <<
")" << std::endl;
398 if (m_writer == m_readers[R]) {
399 #ifdef DEBUG_RINGBUFFER 400 std::cerr <<
"WARNING: No sample available" 404 memset(&t, 0,
sizeof(T));
407 T value = m_buffer[m_readers[R]];
409 if (++m_readers[R] == m_size) m_readers[R] = 0;
413 template <
typename T,
int N>
417 #ifdef DEBUG_RINGBUFFER 418 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::peek(dest, " << n <<
", " << R <<
")" << std::endl;
421 int available = getReadSpace(R);
423 #ifdef DEBUG_RINGBUFFER 424 std::cerr <<
"WARNING: Only " << available <<
" samples available" 427 memset(destination + available, 0, (n - available) *
sizeof(T));
430 if (n == 0)
return n;
432 int here = m_size - m_readers[R];
434 memcpy(destination, m_buffer + m_readers[R], n *
sizeof(T));
436 memcpy(destination, m_buffer + m_readers[R], here *
sizeof(T));
437 memcpy(destination + here, m_buffer, (n - here) *
sizeof(T));
440 #ifdef DEBUG_RINGBUFFER 441 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::peek: read " << n << std::endl;
447 template <
typename T,
int N>
451 #ifdef DEBUG_RINGBUFFER 452 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::peek(" << R <<
")" << std::endl;
455 if (m_writer == m_readers[R]) {
456 #ifdef DEBUG_RINGBUFFER 457 std::cerr <<
"WARNING: No sample available" 461 memset(&t, 0,
sizeof(T));
464 T value = m_buffer[m_readers[R]];
468 template <
typename T,
int N>
472 #ifdef DEBUG_RINGBUFFER 473 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::skip(" << n <<
", " << R <<
")" << std::endl;
476 int available = getReadSpace(R);
478 #ifdef DEBUG_RINGBUFFER 479 std::cerr <<
"WARNING: Only " << available <<
" samples available" 484 if (n == 0)
return n;
485 m_readers[R] = (m_readers[R] + n) % m_size;
489 template <
typename T,
int N>
493 #ifdef DEBUG_RINGBUFFER 494 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::write(" << n <<
")" << std::endl;
497 int available = getWriteSpace();
499 #ifdef DEBUG_RINGBUFFER 500 std::cerr <<
"WARNING: Only room for " << available <<
" samples" 505 if (n == 0)
return n;
507 int here = m_size - m_writer;
509 memcpy(m_buffer + m_writer, source, n *
sizeof(T));
511 memcpy(m_buffer + m_writer, source, here *
sizeof(T));
512 memcpy(m_buffer, source + here, (n - here) *
sizeof(T));
516 m_writer = (m_writer + n) % m_size;
518 #ifdef DEBUG_RINGBUFFER 519 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::write: wrote " << n <<
", writer now " << m_writer << std::endl;
525 template <
typename T,
int N>
529 #ifdef DEBUG_RINGBUFFER 530 std::cerr <<
"RingBuffer<T," << N <<
">[" <<
this <<
"]::zero(" << n <<
")" << std::endl;
533 int available = getWriteSpace();
535 #ifdef DEBUG_RINGBUFFER 536 std::cerr <<
"WARNING: Only room for " << available <<
" samples" 541 if (n == 0)
return n;
543 int here = m_size - m_writer;
545 memset(m_buffer + m_writer, 0, n *
sizeof(T));
547 memset(m_buffer + m_writer, 0, here *
sizeof(T));
548 memset(m_buffer, 0, (n - here) *
sizeof(T));
552 m_writer = (m_writer + n) % m_size;
556 #endif // _RINGBUFFER_H_ RingBuffer & operator=(const RingBuffer &)
T peekOne(int R=0) const
Read one sample from the buffer, if available, without advancing the read pointer – i....
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.
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.
bool mlock()
Lock the ring buffer into physical memory.
RingBuffer(int n)
Create a ring buffer with room to write n 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 getReadSpace(int R=0) const
Return the amount of data available for reading by reader R, in samples.
int getWriteSpace() const
Return the amount of space available for writing, in samples.
int readAdding(T *destination, int n, int R=0)
Read n samples from the buffer, for reader R, adding them to the destination.
RingBuffer< T, N > * resized(int newSize) const
Return a new ring buffer (allocated with "new" – caller must delete when no longer needed) of the giv...
int zero(int n)
Write n zero-value samples to the buffer.
int getSize() const
Return the total capacity of the ring buffer in samples.