17 #ifndef DISTRHO_RING_BUFFER_HPP_INCLUDED
18 #define DISTRHO_RING_BUFFER_HPP_INCLUDED
20 #include "../DistrhoUtils.hpp"
94 static const uint32_t size = 4096;
95 uint32_t head, tail, wrtn;
96 bool invalidateCommit;
105 static const uint32_t size = 16384;
106 uint32_t head, tail, wrtn;
107 bool invalidateCommit;
116 static const uint32_t size = 65536;
117 uint32_t head, tail, wrtn;
118 bool invalidateCommit;
122 #ifdef DISTRHO_PROPER_CPP11_SUPPORT
123 # define HeapBuffer_INIT {0, 0, 0, 0, false, nullptr}
124 # define StackBuffer_INIT {0, 0, 0, false, {0}}
126 # define HeapBuffer_INIT
127 # define StackBuffer_INIT
166 template <
class BufferStruct>
178 errorWriting(
false) {}
191 bool isDataAvailableForReading()
const noexcept;
196 bool isEmpty()
const noexcept
198 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr,
false);
200 return (buffer->buf ==
nullptr || buffer->head == buffer->tail);
206 uint32_t getSize()
const noexcept
208 return buffer !=
nullptr ? buffer->size : 0;
214 uint32_t getReadableDataSize()
const noexcept
216 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr, 0);
218 const uint32_t wrap = buffer->head >= buffer->tail ? 0 : buffer->size;
220 return wrap + buffer->head - buffer->tail;
226 uint32_t getWritableDataSize()
const noexcept
228 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr, 0);
230 const uint32_t wrap = buffer->tail > buffer->wrtn ? 0 : buffer->size;
232 return wrap + buffer->tail - buffer->wrtn - 1;
242 void clearData() noexcept
244 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr,);
249 buffer->invalidateCommit =
false;
251 std::memset(buffer->buf, 0, buffer->size);
258 void flush() noexcept
260 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr,);
262 buffer->head = buffer->tail = buffer->wrtn = 0;
263 buffer->invalidateCommit =
false;
265 errorWriting =
false;
275 bool readBool() noexcept
278 return tryRead(&b,
sizeof(
bool)) ? b :
false;
285 uint8_t readByte() noexcept
288 return tryRead(&B,
sizeof(uint8_t)) ? B : 0;
295 int16_t readShort() noexcept
298 return tryRead(&s,
sizeof(int16_t)) ? s : 0;
305 uint16_t readUShort() noexcept
308 return tryRead(&us,
sizeof(uint16_t)) ? us : 0;
315 int32_t readInt() noexcept
318 return tryRead(&i,
sizeof(int32_t)) ? i : 0;
325 uint32_t readUInt() noexcept
328 return tryRead(&ui,
sizeof(int32_t)) ? ui : 0;
335 int64_t readLong() noexcept
338 return tryRead(&l,
sizeof(int64_t)) ? l : 0;
345 uint64_t readULong() noexcept
348 return tryRead(&ul,
sizeof(int64_t)) ? ul : 0;
355 float readFloat() noexcept
358 return tryRead(&f,
sizeof(
float)) ? f : 0.0f;
365 double readDouble() noexcept
368 return tryRead(&d,
sizeof(
double)) ? d : 0.0;
380 DISTRHO_SAFE_ASSERT_RETURN(data !=
nullptr,
false);
381 DISTRHO_SAFE_ASSERT_RETURN(size > 0,
false);
383 if (tryRead(data, size))
386 std::memset(data, 0, size);
397 template <
typename T>
400 if (tryRead(&type,
sizeof(T)))
403 std::memset(&type, 0,
sizeof(T));
413 bool writeBool(
const bool value) noexcept
415 return tryWrite(&value,
sizeof(
bool));
421 bool writeByte(
const uint8_t value) noexcept
423 return tryWrite(&value,
sizeof(uint8_t));
429 bool writeShort(
const int16_t value) noexcept
431 return tryWrite(&value,
sizeof(int16_t));
437 bool writeUShort(
const uint16_t value) noexcept
439 return tryWrite(&value,
sizeof(uint16_t));
445 bool writeInt(
const int32_t value) noexcept
447 return tryWrite(&value,
sizeof(int32_t));
453 bool writeUInt(
const uint32_t value) noexcept
455 return tryWrite(&value,
sizeof(uint32_t));
461 bool writeLong(
const int64_t value) noexcept
463 return tryWrite(&value,
sizeof(int64_t));
469 bool writeULong(
const uint64_t value) noexcept
471 return tryWrite(&value,
sizeof(uint64_t));
477 bool writeFloat(
const float value) noexcept
479 return tryWrite(&value,
sizeof(
float));
485 bool writeDouble(
const double value) noexcept
487 return tryWrite(&value,
sizeof(
double));
496 DISTRHO_SAFE_ASSERT_RETURN(data !=
nullptr,
false);
497 DISTRHO_SAFE_ASSERT_RETURN(size > 0,
false);
499 return tryWrite(data, size);
506 template <
typename T>
509 return tryWrite(&type,
sizeof(T));
520 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr,
false);
522 if (buffer->invalidateCommit)
524 buffer->wrtn = buffer->head;
525 buffer->invalidateCommit =
false;
530 DISTRHO_SAFE_ASSERT_RETURN(buffer->head != buffer->wrtn,
false);
533 buffer->head = buffer->wrtn;
534 errorWriting =
false;
543 void setRingBuffer(BufferStruct*
const ringBuf,
const bool clearRingBufferData) noexcept
545 DISTRHO_SAFE_ASSERT_RETURN(buffer != ringBuf,);
549 if (clearRingBufferData && ringBuf !=
nullptr)
557 bool tryRead(
void*
const buf,
const uint32_t size) noexcept
559 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr,
false);
560 #if defined(__clang__)
561 #pragma clang diagnostic push
562 #pragma clang diagnostic ignored "-Wtautological-pointer-compare"
564 DISTRHO_SAFE_ASSERT_RETURN(buffer->buf !=
nullptr,
false);
565 #if defined(__clang__)
566 #pragma clang diagnostic pop
568 DISTRHO_SAFE_ASSERT_RETURN(buf !=
nullptr,
false);
569 DISTRHO_SAFE_ASSERT_RETURN(size > 0,
false);
570 DISTRHO_SAFE_ASSERT_RETURN(size < buffer->size,
false);
573 if (buffer->head == buffer->tail)
576 uint8_t*
const bytebuf =
static_cast<uint8_t*
>(buf);
578 const uint32_t head = buffer->head;
579 const uint32_t tail = buffer->tail;
580 const uint32_t wrap = head > tail ? 0 : buffer->size;
582 if (size > wrap + head - tail)
587 d_stderr2(
"RingBuffer::tryRead(%p, %lu): failed, not enough space", buf, (ulong)size);
592 uint32_t readto = tail + size;
594 if (readto > buffer->size)
596 readto -= buffer->size;
600 std::memcpy(bytebuf, buffer->buf + tail, 1);
604 const uint32_t firstpart(buffer->size - tail);
605 std::memcpy(bytebuf, buffer->buf + tail, firstpart);
606 std::memcpy(bytebuf + firstpart, buffer->buf, readto);
611 std::memcpy(bytebuf, buffer->buf + tail, size);
613 if (readto == buffer->size)
617 buffer->tail = readto;
618 errorReading =
false;
623 bool tryWrite(
const void*
const buf,
const uint32_t size) noexcept
625 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr,
false);
626 DISTRHO_SAFE_ASSERT_RETURN(buf !=
nullptr,
false);
627 DISTRHO_SAFE_ASSERT_RETURN(size > 0,
false);
628 DISTRHO_SAFE_ASSERT_UINT2_RETURN(size < buffer->size, size, buffer->size,
false);
630 const uint8_t*
const bytebuf =
static_cast<const uint8_t*
>(buf);
632 const uint32_t tail = buffer->tail;
633 const uint32_t wrtn = buffer->wrtn;
634 const uint32_t wrap = tail > wrtn ? 0 : buffer->size;
636 if (size >= wrap + tail - wrtn)
641 d_stderr2(
"RingBuffer::tryWrite(%p, %lu): failed, not enough space", buf, (ulong)size);
643 buffer->invalidateCommit =
true;
647 uint32_t writeto = wrtn + size;
649 if (writeto > buffer->size)
651 writeto -= buffer->size;
655 std::memcpy(buffer->buf, bytebuf, 1);
659 const uint32_t firstpart(buffer->size - wrtn);
660 std::memcpy(buffer->buf + wrtn, bytebuf, firstpart);
661 std::memcpy(buffer->buf, bytebuf + firstpart, writeto);
666 std::memcpy(buffer->buf + wrtn, bytebuf, size);
668 if (writeto == buffer->size)
672 buffer->wrtn = writeto;
678 BufferStruct* buffer;
686 DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION
690 template <
class BufferStruct>
693 return (buffer !=
nullptr && buffer->head != buffer->tail);
699 return (buffer !=
nullptr && buffer->buf !=
nullptr && buffer->head != buffer->tail);
715 : heapBuffer(HeapBuffer_INIT)
717 #ifndef DISTRHO_PROPER_CPP11_SUPPORT
718 std::memset(&heapBuffer, 0,
sizeof(heapBuffer));
725 if (heapBuffer.
buf ==
nullptr)
728 delete[] heapBuffer.
buf;
729 heapBuffer.
buf =
nullptr;
735 DISTRHO_SAFE_ASSERT_RETURN(heapBuffer.
buf ==
nullptr,
false);
736 DISTRHO_SAFE_ASSERT_RETURN(size > 0,
false);
741 heapBuffer.
buf =
new uint8_t[p2size];
742 } DISTRHO_SAFE_EXCEPTION_RETURN(
"HeapRingBuffer::createBuffer",
false);
744 heapBuffer.
size = p2size;
745 setRingBuffer(&heapBuffer,
true);
752 DISTRHO_SAFE_ASSERT_RETURN(heapBuffer.
buf !=
nullptr,);
754 setRingBuffer(
nullptr,
false);
756 delete[] heapBuffer.
buf;
757 heapBuffer.
buf =
nullptr;
763 DISTRHO_SAFE_ASSERT_RETURN(other.heapBuffer.
size == heapBuffer.
size,);
765 std::memcpy(&heapBuffer, &other.heapBuffer,
sizeof(
HeapBuffer) -
sizeof(uint8_t*));
766 std::memcpy(heapBuffer.
buf, other.heapBuffer.
buf,
sizeof(uint8_t) * heapBuffer.
size);
774 DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION
790 : stackBuffer(StackBuffer_INIT)
792 #ifndef DISTRHO_PROPER_CPP11_SUPPORT
793 std::memset(&stackBuffer, 0,
sizeof(stackBuffer));
795 setRingBuffer(&stackBuffer,
true);
802 DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION
Definition: RingBuffer.hpp:711
HeapRingBuffer() noexcept
Definition: RingBuffer.hpp:714
void deleteBuffer() noexcept
Definition: RingBuffer.hpp:750
bool createBuffer(const uint32_t size) noexcept
Definition: RingBuffer.hpp:733
~HeapRingBuffer() noexcept override
Definition: RingBuffer.hpp:723
Definition: RingBuffer.hpp:168
bool writeCustomType(const T &type) noexcept
Definition: RingBuffer.hpp:507
bool writeCustomData(const void *const data, const uint32_t size) noexcept
Definition: RingBuffer.hpp:494
bool readCustomType(T &type) noexcept
Definition: RingBuffer.hpp:398
bool readCustomData(void *const data, const uint32_t size) noexcept
Definition: RingBuffer.hpp:378
bool commitWrite() noexcept
Definition: RingBuffer.hpp:518
Definition: RingBuffer.hpp:786
SmallStackRingBuffer() noexcept
Definition: RingBuffer.hpp:789
static uint32_t d_nextPowerOf2(uint32_t size) noexcept
Definition: DistrhoUtils.hpp:308
#define END_NAMESPACE_DISTRHO
Definition: DistrhoInfo.hpp:949
#define START_NAMESPACE_DISTRHO
Definition: DistrhoInfo.hpp:943
static void d_stderr2(const char *const fmt,...) noexcept
Definition: DistrhoUtils.hpp:171
Definition: RingBuffer.hpp:104
Definition: RingBuffer.hpp:49
bool invalidateCommit
Definition: RingBuffer.hpp:80
uint32_t wrtn
Definition: RingBuffer.hpp:74
uint32_t head
Definition: RingBuffer.hpp:60
uint32_t size
Definition: RingBuffer.hpp:54
uint32_t tail
Definition: RingBuffer.hpp:67
uint8_t * buf
Definition: RingBuffer.hpp:86
Definition: RingBuffer.hpp:115
Definition: RingBuffer.hpp:93