| 
							- /*
 -  * LV2 Atom Ring Buffer
 -  * Copyright (C) 2012-2023 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 LV2_ATOM_RING_BUFFER_HPP_INCLUDED
 - #define LV2_ATOM_RING_BUFFER_HPP_INCLUDED
 - 
 - #include "CarlaMutex.hpp"
 - #include "CarlaRingBuffer.hpp"
 - 
 - #include "lv2/atom.h"
 - 
 - // --------------------------------------------------------------------------------------------------------------------
 - 
 - class Lv2AtomRingBuffer : public CarlaRingBufferControl<HeapBuffer>
 - {
 - public:
 -     Lv2AtomRingBuffer() noexcept
 -         : fMutex(),
 -           fHeapBuffer{0, 0, 0, 0, false, nullptr},
 -           fNeedsDataDelete(true)
 -     {
 -     }
 - 
 -     Lv2AtomRingBuffer(Lv2AtomRingBuffer& ringBuf, uint8_t buf[]) noexcept
 -         : fMutex(),
 -           fHeapBuffer{0, 0, 0, 0, false, nullptr},
 -           fNeedsDataDelete(false)
 -     {
 -         fHeapBuffer.buf  = buf;
 -         fHeapBuffer.size = ringBuf.fHeapBuffer.size;
 - 
 -         {
 -             const CarlaMutexLocker cml(ringBuf.fMutex);
 -             fHeapBuffer.copyDataFrom(ringBuf.fHeapBuffer);
 -             ringBuf.clearData();
 -         }
 - 
 -         setRingBuffer(&fHeapBuffer, false);
 -     }
 - 
 -     ~Lv2AtomRingBuffer() noexcept
 -     {
 -         if (fHeapBuffer.buf == nullptr || ! fNeedsDataDelete)
 -             return;
 - 
 -         delete[] fHeapBuffer.buf;
 -         fHeapBuffer.buf = nullptr;
 -     }
 - 
 -     // ----------------------------------------------------------------------------------------------------------------
 - 
 -     void createBuffer(const uint32_t size, const bool mlock) noexcept
 -     {
 -         CARLA_SAFE_ASSERT_RETURN(fHeapBuffer.buf == nullptr,);
 -         CARLA_SAFE_ASSERT_RETURN(fNeedsDataDelete,);
 -         CARLA_SAFE_ASSERT_RETURN(size > 0,);
 - 
 -         const uint32_t p2size = carla_nextPowerOf2(size);
 - 
 -         try {
 -             fHeapBuffer.buf = new uint8_t[p2size];
 -         } CARLA_SAFE_EXCEPTION_RETURN("Lv2AtomRingBuffer::createBuffer",);
 - 
 -         fHeapBuffer.size = p2size;
 -         setRingBuffer(&fHeapBuffer, true);
 - 
 -         if (mlock)
 -         {
 -             carla_mlock(&fHeapBuffer, sizeof(fHeapBuffer));
 -             carla_mlock(fHeapBuffer.buf, p2size);
 -         }
 -     }
 - 
 -     void deleteBuffer() noexcept
 -     {
 -         CARLA_SAFE_ASSERT_RETURN(fHeapBuffer.buf != nullptr,);
 -         CARLA_SAFE_ASSERT_RETURN(fNeedsDataDelete,);
 - 
 -         setRingBuffer(nullptr, false);
 - 
 -         delete[] fHeapBuffer.buf;
 -         fHeapBuffer.buf  = nullptr;
 -         fHeapBuffer.size = 0;
 -     }
 - 
 -     uint32_t getSize() const noexcept
 -     {
 -         return fHeapBuffer.size;
 -     }
 - 
 -     // ----------------------------------------------------------------------------------------------------------------
 - 
 -     bool tryLock() const noexcept
 -     {
 -         return fMutex.tryLock();
 -     }
 - 
 -     void unlock() const noexcept
 -     {
 -         fMutex.unlock();
 -     }
 - 
 -     // ----------------------------------------------------------------------------------------------------------------
 - 
 -     // NOTE: must have been locked before
 -     bool get(uint32_t& portIndex, LV2_Atom* const retAtom) noexcept
 -     {
 -         if (readAtom(portIndex, retAtom))
 -             return true;
 - 
 -         retAtom->size = retAtom->type = 0;
 -         return false;
 -     }
 - 
 -     // NOTE: must NOT been locked, we do that here
 -     bool put(const LV2_Atom* const atom, const uint32_t portIndex) noexcept
 -     {
 -         CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false);
 - 
 -         const CarlaMutexLocker cml(fMutex);
 - 
 -         return writeAtom(atom, static_cast<int32_t>(portIndex));
 -     }
 - 
 -     // NOTE: must NOT been locked, we do that here
 -     bool putChunk(const LV2_Atom* const atom, const void* const data, const uint32_t portIndex) noexcept
 -     {
 -         CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false);
 -         CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
 - 
 -         const CarlaMutexLocker cml(fMutex);
 - 
 -         return writeAtomChunk(atom, data, static_cast<int32_t>(portIndex));
 -     }
 - 
 - protected:
 -     // ----------------------------------------------------------------------------------------------------------------
 - 
 -     bool readAtom(uint32_t& portIndex, LV2_Atom* const retAtom) noexcept
 -     {
 -         const uint32_t maxAtomSize = retAtom->size - sizeof(LV2_Atom);
 - 
 -         LV2_Atom atom = {};
 - 
 -         if (! tryRead(&atom, sizeof(LV2_Atom)))
 -             return false;
 -         if (atom.size == 0 || atom.type == 0)
 -             return false;
 - 
 -         CARLA_SAFE_ASSERT_UINT2_RETURN(atom.size < maxAtomSize, atom.size, maxAtomSize, false);
 - 
 -         int32_t index = -1;
 -         if (! tryRead(&index, sizeof(int32_t)))
 -             return false;
 -         if (index < 0)
 -             return false;
 - 
 -         if (! tryRead(retAtom + 1, atom.size))
 -             return false;
 - 
 -         portIndex = static_cast<uint32_t>(index);
 -         retAtom->size = atom.size;
 -         retAtom->type = atom.type;
 -         return true;
 -     }
 - 
 -     // ----------------------------------------------------------------------------------------------------------------
 - 
 -     bool writeAtom(const LV2_Atom* const atom, const int32_t portIndex) noexcept
 -     {
 -         if (tryWrite(atom, sizeof(LV2_Atom)) && tryWrite(&portIndex, sizeof(int32_t)))
 -             tryWrite(LV2_ATOM_BODY_CONST(atom), atom->size);
 -         return commitWrite();
 -     }
 - 
 -     bool writeAtomChunk(const LV2_Atom* const atom, const void* const data, const int32_t portIndex) noexcept
 -     {
 -         if (tryWrite(atom, sizeof(LV2_Atom)) && tryWrite(&portIndex, sizeof(int32_t)))
 -             tryWrite(data, atom->size);
 -         return commitWrite();
 -     }
 - 
 -     // ----------------------------------------------------------------------------------------------------------------
 - 
 - private:
 -     CarlaMutex fMutex;
 -     HeapBuffer fHeapBuffer;
 -     const bool fNeedsDataDelete;
 - 
 -     friend class Lv2AtomQueue;
 - 
 -     CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION
 -     CARLA_DECLARE_NON_COPYABLE(Lv2AtomRingBuffer)
 - };
 - 
 - // --------------------------------------------------------------------------------------------------------------------
 - 
 - #endif // LV2_ATOM_RING_BUFFER_HPP_INCLUDED
 
 
  |