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 getReadableDataSize()
const noexcept
208 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr, 0);
210 const uint32_t wrap = buffer->head > buffer->tail ? 0 : buffer->size;
212 return wrap + buffer->head - buffer->tail;
218 uint32_t getWritableDataSize()
const noexcept
220 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr, 0);
222 const uint32_t wrap = (buffer->tail > buffer->wrtn) ? 0 : buffer->size;
224 return wrap + buffer->tail - buffer->wrtn;
234 void clearData() noexcept
236 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr,);
241 buffer->invalidateCommit =
false;
243 std::memset(buffer->buf, 0, buffer->size);
253 bool readBool() noexcept
256 return tryRead(&b,
sizeof(
bool)) ? b :
false;
263 uint8_t readByte() noexcept
266 return tryRead(&B,
sizeof(uint8_t)) ? B : 0;
273 int16_t readShort() noexcept
276 return tryRead(&s,
sizeof(int16_t)) ? s : 0;
283 uint16_t readUShort() noexcept
286 return tryRead(&us,
sizeof(uint16_t)) ? us : 0;
293 int32_t readInt() noexcept
296 return tryRead(&i,
sizeof(int32_t)) ? i : 0;
303 uint32_t readUInt() noexcept
306 return tryRead(&ui,
sizeof(int32_t)) ? ui : 0;
313 int64_t readLong() noexcept
316 return tryRead(&l,
sizeof(int64_t)) ? l : 0;
323 uint64_t readULong() noexcept
326 return tryRead(&ul,
sizeof(int64_t)) ? ul : 0;
333 float readFloat() noexcept
336 return tryRead(&f,
sizeof(
float)) ? f : 0.0f;
343 double readDouble() noexcept
346 return tryRead(&d,
sizeof(
double)) ? d : 0.0;
358 DISTRHO_SAFE_ASSERT_RETURN(data !=
nullptr,
false);
359 DISTRHO_SAFE_ASSERT_RETURN(size > 0,
false);
361 if (tryRead(data, size))
364 std::memset(data, 0, size);
375 template <
typename T>
378 if (tryRead(&type,
sizeof(T)))
381 std::memset(&type, 0,
sizeof(T));
391 bool writeBool(
const bool value) noexcept
393 return tryWrite(&value,
sizeof(
bool));
399 bool writeByte(
const uint8_t value) noexcept
401 return tryWrite(&value,
sizeof(uint8_t));
407 bool writeShort(
const int16_t value) noexcept
409 return tryWrite(&value,
sizeof(int16_t));
415 bool writeUShort(
const uint16_t value) noexcept
417 return tryWrite(&value,
sizeof(uint16_t));
423 bool writeInt(
const int32_t value) noexcept
425 return tryWrite(&value,
sizeof(int32_t));
431 bool writeUInt(
const uint32_t value) noexcept
433 return tryWrite(&value,
sizeof(uint32_t));
439 bool writeLong(
const int64_t value) noexcept
441 return tryWrite(&value,
sizeof(int64_t));
447 bool writeULong(
const uint64_t value) noexcept
449 return tryWrite(&value,
sizeof(uint64_t));
455 bool writeFloat(
const float value) noexcept
457 return tryWrite(&value,
sizeof(
float));
463 bool writeDouble(
const double value) noexcept
465 return tryWrite(&value,
sizeof(
double));
474 DISTRHO_SAFE_ASSERT_RETURN(data !=
nullptr,
false);
475 DISTRHO_SAFE_ASSERT_RETURN(size > 0,
false);
477 return tryWrite(data, size);
484 template <
typename T>
487 return tryWrite(&type,
sizeof(T));
498 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr,
false);
500 if (buffer->invalidateCommit)
502 buffer->wrtn = buffer->head;
503 buffer->invalidateCommit =
false;
508 DISTRHO_SAFE_ASSERT_RETURN(buffer->head != buffer->wrtn,
false);
511 buffer->head = buffer->wrtn;
512 errorWriting =
false;
521 void setRingBuffer(BufferStruct*
const ringBuf,
const bool clearRingBufferData) noexcept
523 DISTRHO_SAFE_ASSERT_RETURN(buffer != ringBuf,);
527 if (clearRingBufferData && ringBuf !=
nullptr)
535 bool tryRead(
void*
const buf,
const uint32_t size) noexcept
537 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr,
false);
538 #if defined(__clang__)
539 # pragma clang diagnostic push
540 # pragma clang diagnostic ignored "-Wtautological-pointer-compare"
542 DISTRHO_SAFE_ASSERT_RETURN(buffer->buf !=
nullptr,
false);
543 #if defined(__clang__)
544 # pragma clang diagnostic pop
546 DISTRHO_SAFE_ASSERT_RETURN(buf !=
nullptr,
false);
547 DISTRHO_SAFE_ASSERT_RETURN(size > 0,
false);
548 DISTRHO_SAFE_ASSERT_RETURN(size < buffer->size,
false);
551 if (buffer->head == buffer->tail)
554 uint8_t*
const bytebuf(
static_cast<uint8_t*
>(buf));
556 const uint32_t head(buffer->head);
557 const uint32_t tail(buffer->tail);
558 const uint32_t wrap((head > tail) ? 0 : buffer->size);
560 if (size > wrap + head - tail)
565 d_stderr2(
"RingBuffer::tryRead(%p, %lu): failed, not enough space", buf, (ulong)size);
570 uint32_t readto(tail + size);
572 if (readto > buffer->size)
574 readto -= buffer->size;
578 std::memcpy(bytebuf, buffer->buf + tail, 1);
582 const uint32_t firstpart(buffer->size - tail);
583 std::memcpy(bytebuf, buffer->buf + tail, firstpart);
584 std::memcpy(bytebuf + firstpart, buffer->buf, readto);
589 std::memcpy(bytebuf, buffer->buf + tail, size);
591 if (readto == buffer->size)
595 buffer->tail = readto;
596 errorReading =
false;
601 bool tryWrite(
const void*
const buf,
const uint32_t size) noexcept
603 DISTRHO_SAFE_ASSERT_RETURN(buffer !=
nullptr,
false);
604 DISTRHO_SAFE_ASSERT_RETURN(buf !=
nullptr,
false);
605 DISTRHO_SAFE_ASSERT_RETURN(size > 0,
false);
606 DISTRHO_SAFE_ASSERT_UINT2_RETURN(size < buffer->size, size, buffer->size,
false);
608 const uint8_t*
const bytebuf(
static_cast<const uint8_t*
>(buf));
610 const uint32_t tail(buffer->tail);
611 const uint32_t wrtn(buffer->wrtn);
612 const uint32_t wrap((tail > wrtn) ? 0 : buffer->size);
614 if (size >= wrap + tail - wrtn)
619 d_stderr2(
"RingBuffer::tryWrite(%p, %lu): failed, not enough space", buf, (ulong)size);
621 buffer->invalidateCommit =
true;
625 uint32_t writeto(wrtn + size);
627 if (writeto > buffer->size)
629 writeto -= buffer->size;
633 std::memcpy(buffer->buf, bytebuf, 1);
637 const uint32_t firstpart(buffer->size - wrtn);
638 std::memcpy(buffer->buf + wrtn, bytebuf, firstpart);
639 std::memcpy(buffer->buf, bytebuf + firstpart, writeto);
644 std::memcpy(buffer->buf + wrtn, bytebuf, size);
646 if (writeto == buffer->size)
650 buffer->wrtn = writeto;
656 BufferStruct* buffer;
664 DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION
668 template <
class BufferStruct>
671 return (buffer !=
nullptr && buffer->head != buffer->tail);
677 return (buffer !=
nullptr && buffer->buf !=
nullptr && buffer->head != buffer->tail);
693 : heapBuffer(HeapBuffer_INIT)
695 #ifndef DISTRHO_PROPER_CPP11_SUPPORT
696 std::memset(&heapBuffer, 0,
sizeof(heapBuffer));
703 if (heapBuffer.
buf ==
nullptr)
706 delete[] heapBuffer.
buf;
707 heapBuffer.
buf =
nullptr;
713 DISTRHO_SAFE_ASSERT_RETURN(heapBuffer.
buf ==
nullptr,
false);
714 DISTRHO_SAFE_ASSERT_RETURN(size > 0,
false);
719 heapBuffer.
buf =
new uint8_t[p2size];
720 } DISTRHO_SAFE_EXCEPTION_RETURN(
"HeapRingBuffer::createBuffer",
false);
722 heapBuffer.
size = p2size;
723 setRingBuffer(&heapBuffer,
true);
730 DISTRHO_SAFE_ASSERT_RETURN(heapBuffer.
buf !=
nullptr,);
732 setRingBuffer(
nullptr,
false);
734 delete[] heapBuffer.
buf;
735 heapBuffer.
buf =
nullptr;
741 DISTRHO_SAFE_ASSERT_RETURN(other.heapBuffer.
size == heapBuffer.
size,);
743 std::memcpy(&heapBuffer, &other.heapBuffer,
sizeof(
HeapBuffer) -
sizeof(uint8_t*));
744 std::memcpy(heapBuffer.
buf, other.heapBuffer.
buf,
sizeof(uint8_t) * heapBuffer.
size);
752 DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION
768 : stackBuffer(StackBuffer_INIT)
770 #ifndef DISTRHO_PROPER_CPP11_SUPPORT
771 std::memset(&stackBuffer, 0,
sizeof(stackBuffer));
773 setRingBuffer(&stackBuffer,
true);
780 DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION
Definition: RingBuffer.hpp:689
HeapRingBuffer() noexcept
Definition: RingBuffer.hpp:692
void deleteBuffer() noexcept
Definition: RingBuffer.hpp:728
bool createBuffer(const uint32_t size) noexcept
Definition: RingBuffer.hpp:711
~HeapRingBuffer() noexcept override
Definition: RingBuffer.hpp:701
Definition: RingBuffer.hpp:168
bool writeCustomType(const T &type) noexcept
Definition: RingBuffer.hpp:485
bool writeCustomData(const void *const data, const uint32_t size) noexcept
Definition: RingBuffer.hpp:472
bool readCustomType(T &type) noexcept
Definition: RingBuffer.hpp:376
bool readCustomData(void *const data, const uint32_t size) noexcept
Definition: RingBuffer.hpp:356
bool commitWrite() noexcept
Definition: RingBuffer.hpp:496
Definition: RingBuffer.hpp:764
SmallStackRingBuffer() noexcept
Definition: RingBuffer.hpp:767
static uint32_t d_nextPowerOf2(uint32_t size) noexcept
Definition: DistrhoUtils.hpp:298
#define END_NAMESPACE_DISTRHO
Definition: DistrhoInfo.hpp:834
#define START_NAMESPACE_DISTRHO
Definition: DistrhoInfo.hpp:828
static void d_stderr2(const char *const fmt,...) noexcept
Definition: DistrhoUtils.hpp:161
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