|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- /*
- * Carla Ring Buffer
- * Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * For a full copy of the GNU General Public License see the doc/GPL.txt file.
- */
-
- #ifndef CARLA_RING_BUFFER_HPP_INCLUDED
- #define CARLA_RING_BUFFER_HPP_INCLUDED
-
- #include "CarlaUtils.hpp"
-
- // -----------------------------------------------------------------------
- // RingBuffer structs
-
- struct HeapRingBuffer {
- uint32_t size;
- int32_t head, tail, written;
- bool invalidateCommit;
- char* buf;
-
- HeapRingBuffer& operator=(const HeapRingBuffer& rb)
- {
- CARLA_SAFE_ASSERT_RETURN(size == rb.size, *this);
-
- size = rb.size;
- head = rb.head;
- tail = rb.tail;
- written = rb.written;
- invalidateCommit = rb.invalidateCommit;
- std::memcpy(buf, rb.buf, size);
-
- return *this;
- }
- };
-
- struct StackRingBuffer {
- static const uint32_t size = 4096;
- int32_t head, tail, written;
- bool invalidateCommit;
- char buf[size];
- };
-
- PRE_PACKED_STRUCTURE
- struct StackPackedRingBuffer {
- static const uint32_t size = 4096;
- int32_t head, tail, written;
- bool invalidateCommit;
- char buf[size];
- } POST_PACKED_STRUCTURE;
-
- // -----------------------------------------------------------------------
- // RingBufferControl templated class
-
- template <class RingBufferStruct>
- class RingBufferControl
- {
- public:
- RingBufferControl(RingBufferStruct* const ringBuf) noexcept
- : fRingBuf(ringBuf)
- {
- if (ringBuf != nullptr)
- clear();
- }
-
- void clear() noexcept
- {
- CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,);
-
- fRingBuf->head = 0;
- fRingBuf->tail = 0;
- fRingBuf->written = 0;
- fRingBuf->invalidateCommit = false;
-
- if (fRingBuf->size > 0)
- carla_zeroChar(fRingBuf->buf, fRingBuf->size);
- }
-
- void setRingBuffer(RingBufferStruct* const ringBuf, const bool reset) noexcept
- {
- CARLA_SAFE_ASSERT_RETURN(ringBuf != nullptr,);
- CARLA_SAFE_ASSERT_RETURN(ringBuf != fRingBuf,);
-
- fRingBuf = ringBuf;
-
- if (reset)
- clear();
- }
-
- // -------------------------------------------------------------------
-
- bool commitWrite() noexcept
- {
- CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr, false);
-
- if (fRingBuf->invalidateCommit)
- {
- fRingBuf->written = fRingBuf->head;
- fRingBuf->invalidateCommit = false;
- return false;
- }
- else
- {
- fRingBuf->head = fRingBuf->written;
- return true;
- }
- }
-
- bool isDataAvailable() const noexcept
- {
- CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr, false);
-
- return (fRingBuf->head != fRingBuf->tail);
- }
-
- // -------------------------------------------------------------------
-
- char readChar() noexcept
- {
- char c = '\0';
- tryRead(&c, sizeof(char));
- return c;
- }
-
- int32_t readInt() noexcept
- {
- int32_t i = 0;
- tryRead(&i, sizeof(int32_t));
- return i;
- }
-
- uint32_t readUInt() noexcept
- {
- int32_t i = -1;
- tryRead(&i, sizeof(int32_t));
- return (i >= 0) ? static_cast<uint32_t>(i) : 0;
- }
-
- int64_t readLong() noexcept
- {
- int64_t l = 0;
- tryRead(&l, sizeof(int64_t));
- return l;
- }
-
- float readFloat() noexcept
- {
- float f = 0.0f;
- tryRead(&f, sizeof(float));
- return f;
- }
-
- // -------------------------------------------------------------------
-
- void writeChar(const char value) noexcept
- {
- tryWrite(&value, sizeof(char));
- }
-
- void writeInt(const int32_t value) noexcept
- {
- tryWrite(&value, sizeof(int32_t));
- }
-
- void writeLong(const int64_t value) noexcept
- {
- tryWrite(&value, sizeof(int64_t));
- }
-
- void writeFloat(const float value) noexcept
- {
- tryWrite(&value, sizeof(float));
- }
-
- // -------------------------------------------------------------------
-
- protected:
- void tryRead(void* const buf, const size_t size) noexcept
- {
- CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,);
- CARLA_SAFE_ASSERT_RETURN(buf != nullptr,);
- CARLA_SAFE_ASSERT_RETURN(size != 0,);
- CARLA_SAFE_ASSERT_RETURN(size < fRingBuf->size,);
-
- // this should not happen
- CARLA_ASSERT(fRingBuf->head >= 0);
- CARLA_ASSERT(fRingBuf->tail >= 0);
- CARLA_ASSERT(fRingBuf->written >= 0);
-
- // empty
- if (fRingBuf->head == fRingBuf->tail)
- return;
-
- char* const charbuf(static_cast<char*>(buf));
-
- const size_t head(static_cast<size_t>(fRingBuf->head));
- const size_t tail(static_cast<size_t>(fRingBuf->tail));
- const size_t wrap((head < tail) ? fRingBuf->size : 0);
-
- if (head - tail + wrap < size)
- {
- carla_stderr2("RingBufferControl::tryRead() - failed");
- return;
- }
-
- size_t readto = tail + size;
-
- if (readto >= fRingBuf->size)
- {
- readto -= fRingBuf->size;
- const size_t firstpart(fRingBuf->size - tail);
- std::memcpy(charbuf, fRingBuf->buf + tail, firstpart);
- std::memcpy(charbuf + firstpart, fRingBuf->buf, readto);
- }
- else
- {
- std::memcpy(charbuf, fRingBuf->buf + tail, size);
- }
-
- fRingBuf->tail = static_cast<int32_t>(readto);
- }
-
- void tryWrite(const void* const buf, const size_t size) noexcept
- {
- CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,);
- CARLA_SAFE_ASSERT_RETURN(buf != nullptr,);
- CARLA_SAFE_ASSERT_RETURN(size != 0,);
- CARLA_SAFE_ASSERT_RETURN(size < fRingBuf->size,);
-
- // this should not happen
- CARLA_ASSERT(fRingBuf->head >= 0);
- CARLA_ASSERT(fRingBuf->tail >= 0);
- CARLA_ASSERT(fRingBuf->written >= 0);
-
- const char* const charbuf(static_cast<const char*>(buf));
-
- const size_t tail(static_cast<size_t>(fRingBuf->tail));
- const size_t wrtn(static_cast<size_t>(fRingBuf->written));
- const size_t wrap((tail <= wrtn) ? fRingBuf->size : 0);
-
- if (tail - wrtn + wrap <= size)
- {
- carla_stderr2("RingBufferControl::tryWrite() - buffer full!");
- fRingBuf->invalidateCommit = true;
- return;
- }
-
- size_t writeto = wrtn + size;
-
- if (writeto >= fRingBuf->size)
- {
- writeto -= fRingBuf->size;
- const size_t firstpart(fRingBuf->size - wrtn);
- std::memcpy(fRingBuf->buf + wrtn, charbuf, firstpart);
- std::memcpy(fRingBuf->buf, charbuf + firstpart, writeto);
- }
- else
- {
- std::memcpy(fRingBuf->buf + wrtn, charbuf, size);
- }
-
- fRingBuf->written = static_cast<int32_t>(writeto);
- }
-
- private:
- RingBufferStruct* fRingBuf;
-
- CARLA_PREVENT_HEAP_ALLOCATION
- CARLA_DECLARE_NON_COPY_CLASS(RingBufferControl)
- };
-
- // -----------------------------------------------------------------------
-
- #endif // CARLA_RING_BUFFER_HPP_INCLUDED
|