17 #ifndef DISTRHO_RING_BUFFER_HPP_INCLUDED 
   18 #define DISTRHO_RING_BUFFER_HPP_INCLUDED 
   20 #include "../DistrhoUtils.hpp" 
   22 START_NAMESPACE_DISTRHO
 
   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 getAvailableDataSize() 
const noexcept
 
  208         DISTRHO_SAFE_ASSERT_RETURN(buffer != 
nullptr, 0);
 
  210         const uint32_t wrap((buffer->tail > buffer->wrtn) ? 0 : buffer->size);
 
  212         return wrap + buffer->tail - buffer->wrtn;
 
  222     void clearData() noexcept
 
  224         DISTRHO_SAFE_ASSERT_RETURN(buffer != 
nullptr,);
 
  229         buffer->invalidateCommit = 
false;
 
  231         std::memset(buffer->buf, 0, buffer->size);
 
  241     bool readBool() noexcept
 
  244         return tryRead(&b, 
sizeof(
bool)) ? b : 
false;
 
  251     uint8_t readByte() noexcept
 
  254         return tryRead(&B, 
sizeof(uint8_t)) ? B : 0;
 
  261     int16_t readShort() noexcept
 
  264         return tryRead(&s, 
sizeof(int16_t)) ? s : 0;
 
  271     uint16_t readUShort() noexcept
 
  274         return tryRead(&us, 
sizeof(uint16_t)) ? us : 0;
 
  281     int32_t readInt() noexcept
 
  284         return tryRead(&i, 
sizeof(int32_t)) ? i : 0;
 
  291     uint32_t readUInt() noexcept
 
  294         return tryRead(&ui, 
sizeof(int32_t)) ? ui : 0;
 
  301     int64_t readLong() noexcept
 
  304         return tryRead(&l, 
sizeof(int64_t)) ? l : 0;
 
  311     uint64_t readULong() noexcept
 
  314         return tryRead(&ul, 
sizeof(int64_t)) ? ul : 0;
 
  321     float readFloat() noexcept
 
  324         return tryRead(&f, 
sizeof(
float)) ? f : 0.0f;
 
  331     double readDouble() noexcept
 
  334         return tryRead(&d, 
sizeof(
double)) ? d : 0.0;
 
  346         DISTRHO_SAFE_ASSERT_RETURN(data != 
nullptr, 
false);
 
  347         DISTRHO_SAFE_ASSERT_RETURN(size > 0, 
false);
 
  349         if (tryRead(data, size))
 
  352         std::memset(data, 0, size);
 
  363     template <
typename T>
 
  366         if (tryRead(&type, 
sizeof(T)))
 
  369         std::memset(&type, 0, 
sizeof(T));
 
  379     bool writeBool(
const bool value) noexcept
 
  381         return tryWrite(&value, 
sizeof(
bool));
 
  387     bool writeByte(
const uint8_t value) noexcept
 
  389         return tryWrite(&value, 
sizeof(uint8_t));
 
  395     bool writeShort(
const int16_t value) noexcept
 
  397         return tryWrite(&value, 
sizeof(int16_t));
 
  403     bool writeUShort(
const uint16_t value) noexcept
 
  405         return tryWrite(&value, 
sizeof(uint16_t));
 
  411     bool writeInt(
const int32_t value) noexcept
 
  413         return tryWrite(&value, 
sizeof(int32_t));
 
  419     bool writeUInt(
const uint32_t value) noexcept
 
  421         return tryWrite(&value, 
sizeof(uint32_t));
 
  427     bool writeLong(
const int64_t value) noexcept
 
  429         return tryWrite(&value, 
sizeof(int64_t));
 
  435     bool writeULong(
const uint64_t value) noexcept
 
  437         return tryWrite(&value, 
sizeof(uint64_t));
 
  443     bool writeFloat(
const float value) noexcept
 
  445         return tryWrite(&value, 
sizeof(
float));
 
  451     bool writeDouble(
const double value) noexcept
 
  453         return tryWrite(&value, 
sizeof(
double));
 
  462         DISTRHO_SAFE_ASSERT_RETURN(data != 
nullptr, 
false);
 
  463         DISTRHO_SAFE_ASSERT_RETURN(size > 0, 
false);
 
  465         return tryWrite(data, size);
 
  472     template <
typename T>
 
  475         return tryWrite(&type, 
sizeof(T));
 
  486         DISTRHO_SAFE_ASSERT_RETURN(buffer != 
nullptr, 
false);
 
  488         if (buffer->invalidateCommit)
 
  490             buffer->wrtn = buffer->head;
 
  491             buffer->invalidateCommit = 
false;
 
  496         DISTRHO_SAFE_ASSERT_RETURN(buffer->head != buffer->wrtn, 
false);
 
  499         buffer->head = buffer->wrtn;
 
  500         errorWriting = 
false;
 
  509     void setRingBuffer(BufferStruct* 
const ringBuf, 
const bool clearRingBufferData) noexcept
 
  511         DISTRHO_SAFE_ASSERT_RETURN(buffer != ringBuf,);
 
  515         if (clearRingBufferData && ringBuf != 
nullptr)
 
  523     bool tryRead(
void* 
const buf, 
const uint32_t size) noexcept
 
  525         DISTRHO_SAFE_ASSERT_RETURN(buffer != 
nullptr, 
false);
 
  526         #if defined(__clang__) 
  527         # pragma clang diagnostic push 
  528         # pragma clang diagnostic ignored "-Wtautological-pointer-compare" 
  530         DISTRHO_SAFE_ASSERT_RETURN(buffer->buf != 
nullptr, 
false);
 
  531         #if defined(__clang__) 
  532         # pragma clang diagnostic pop 
  534         DISTRHO_SAFE_ASSERT_RETURN(buf != 
nullptr, 
false);
 
  535         DISTRHO_SAFE_ASSERT_RETURN(size > 0, 
false);
 
  536         DISTRHO_SAFE_ASSERT_RETURN(size < buffer->size, 
false);
 
  539         if (buffer->head == buffer->tail)
 
  542         uint8_t* 
const bytebuf(
static_cast<uint8_t*
>(buf));
 
  544         const uint32_t head(buffer->head);
 
  545         const uint32_t tail(buffer->tail);
 
  546         const uint32_t wrap((head > tail) ? 0 : buffer->size);
 
  548         if (size > wrap + head - tail)
 
  553                 d_stderr2(
"RingBuffer::tryRead(%p, %lu): failed, not enough space", buf, (ulong)size);
 
  558         uint32_t readto(tail + size);
 
  560         if (readto > buffer->size)
 
  562             readto -= buffer->size;
 
  566                 std::memcpy(bytebuf, buffer->buf + tail, 1);
 
  570                 const uint32_t firstpart(buffer->size - tail);
 
  571                 std::memcpy(bytebuf, buffer->buf + tail, firstpart);
 
  572                 std::memcpy(bytebuf + firstpart, buffer->buf, readto);
 
  577             std::memcpy(bytebuf, buffer->buf + tail, size);
 
  579             if (readto == buffer->size)
 
  583         buffer->tail = readto;
 
  584         errorReading = 
false;
 
  589     bool tryWrite(
const void* 
const buf, 
const uint32_t size) noexcept
 
  591         DISTRHO_SAFE_ASSERT_RETURN(buffer != 
nullptr, 
false);
 
  592         DISTRHO_SAFE_ASSERT_RETURN(buf != 
nullptr, 
false);
 
  593         DISTRHO_SAFE_ASSERT_RETURN(size > 0, 
false);
 
  594         DISTRHO_SAFE_ASSERT_UINT2_RETURN(size < buffer->size, size, buffer->size, 
false);
 
  596         const uint8_t* 
const bytebuf(
static_cast<const uint8_t*
>(buf));
 
  598         const uint32_t tail(buffer->tail);
 
  599         const uint32_t wrtn(buffer->wrtn);
 
  600         const uint32_t wrap((tail > wrtn) ? 0 : buffer->size);
 
  602         if (size >= wrap + tail - wrtn)
 
  607                 d_stderr2(
"RingBuffer::tryWrite(%p, %lu): failed, not enough space", buf, (ulong)size);
 
  609             buffer->invalidateCommit = 
true;
 
  613         uint32_t writeto(wrtn + size);
 
  615         if (writeto > buffer->size)
 
  617             writeto -= buffer->size;
 
  621                 std::memcpy(buffer->buf, bytebuf, 1);
 
  625                 const uint32_t firstpart(buffer->size - wrtn);
 
  626                 std::memcpy(buffer->buf + wrtn, bytebuf, firstpart);
 
  627                 std::memcpy(buffer->buf, bytebuf + firstpart, writeto);
 
  632             std::memcpy(buffer->buf + wrtn, bytebuf, size);
 
  634             if (writeto == buffer->size)
 
  638         buffer->wrtn = writeto;
 
  644     BufferStruct* buffer;
 
  652     DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION
 
  656 template <
class BufferStruct>
 
  659     return (buffer != 
nullptr && buffer->head != buffer->tail);
 
  665     return (buffer != 
nullptr && buffer->buf != 
nullptr && buffer->head != buffer->tail);
 
  681         : heapBuffer(HeapBuffer_INIT)
 
  683 #ifndef DISTRHO_PROPER_CPP11_SUPPORT 
  684         std::memset(&heapBuffer, 0, 
sizeof(heapBuffer));
 
  691         if (heapBuffer.
buf == 
nullptr)
 
  694         delete[] heapBuffer.
buf;
 
  695         heapBuffer.
buf = 
nullptr;
 
  701         DISTRHO_SAFE_ASSERT_RETURN(heapBuffer.
buf == 
nullptr, 
false);
 
  702         DISTRHO_SAFE_ASSERT_RETURN(size > 0,  
false);
 
  704         const uint32_t p2size = d_nextPowerOf2(size);
 
  707             heapBuffer.
buf = 
new uint8_t[p2size];
 
  708         } DISTRHO_SAFE_EXCEPTION_RETURN(
"HeapRingBuffer::createBuffer", 
false);
 
  710         heapBuffer.
size = p2size;
 
  711         setRingBuffer(&heapBuffer, 
true);
 
  718         DISTRHO_SAFE_ASSERT_RETURN(heapBuffer.
buf != 
nullptr,);
 
  720         setRingBuffer(
nullptr, 
false);
 
  722         delete[] heapBuffer.
buf;
 
  723         heapBuffer.
buf  = 
nullptr;
 
  731     DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION
 
  747         : stackBuffer(StackBuffer_INIT)
 
  749 #ifndef DISTRHO_PROPER_CPP11_SUPPORT 
  750         std::memset(&stackBuffer, 0, 
sizeof(stackBuffer));
 
  752         setRingBuffer(&stackBuffer, 
true);
 
  759     DISTRHO_PREVENT_VIRTUAL_HEAP_ALLOCATION
 
  765 END_NAMESPACE_DISTRHO
 
  767 #endif // DISTRHO_RING_BUFFER_HPP_INCLUDED