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