| @@ -216,3 +216,4 @@ LinuxSampler::InstrumentManager::LoadInstrumentInBackground | |||||
| llround | llround | ||||
| llabs | llabs | ||||
| clock_gettime | clock_gettime | ||||
| RtLinkedList$vtable3 | |||||
| @@ -1864,9 +1864,9 @@ void CarlaPlugin::idle() | |||||
| #endif | #endif | ||||
| } | } | ||||
| const CarlaMutexLocker sl(pData->postRtEvents.mutex); | |||||
| const CarlaMutexLocker sl(pData->postRtEvents.getDataMutex()); | |||||
| for (RtLinkedList<PluginPostRtEvent>::Itenerator it = pData->postRtEvents.data.begin2(); it.valid(); it.next()) | |||||
| for (RtLinkedList<PluginPostRtEvent>::Itenerator it = pData->postRtEvents.getDataIterator(); it.valid(); it.next()) | |||||
| { | { | ||||
| const PluginPostRtEvent& event(it.getValue(kPluginPostRtEventFallback)); | const PluginPostRtEvent& event(it.getValue(kPluginPostRtEventFallback)); | ||||
| CARLA_SAFE_ASSERT_CONTINUE(event.type != kPluginPostRtEventNull); | CARLA_SAFE_ASSERT_CONTINUE(event.type != kPluginPostRtEventNull); | ||||
| @@ -2032,7 +2032,7 @@ void CarlaPlugin::idle() | |||||
| } | } | ||||
| } | } | ||||
| pData->postRtEvents.data.clear(); | |||||
| pData->postRtEvents.clearData(); | |||||
| } | } | ||||
| bool CarlaPlugin::tryLock(const bool forcedOffline) noexcept | bool CarlaPlugin::tryLock(const bool forcedOffline) noexcept | ||||
| @@ -501,40 +501,49 @@ void CarlaPlugin::ProtectedData::Latency::recreateBuffers(const uint32_t newChan | |||||
| // ProtectedData::PostRtEvents | // ProtectedData::PostRtEvents | ||||
| CarlaPlugin::ProtectedData::PostRtEvents::PostRtEvents() noexcept | CarlaPlugin::ProtectedData::PostRtEvents::PostRtEvents() noexcept | ||||
| : mutex(), | |||||
| dataPool(128, 128), | |||||
| : dataPool(128, 128), | |||||
| dataPendingRT(dataPool), | |||||
| data(dataPool), | data(dataPool), | ||||
| dataPendingRT(dataPool) {} | |||||
| dataMutex(), | |||||
| dataPendingMutex() {} | |||||
| CarlaPlugin::ProtectedData::PostRtEvents::~PostRtEvents() noexcept | CarlaPlugin::ProtectedData::PostRtEvents::~PostRtEvents() noexcept | ||||
| { | { | ||||
| clear(); | |||||
| dataMutex.lock(); | |||||
| data.clear(); | |||||
| dataMutex.unlock(); | |||||
| dataPendingMutex.lock(); | |||||
| dataPendingRT.clear(); | |||||
| dataPendingMutex.unlock(); | |||||
| } | } | ||||
| void CarlaPlugin::ProtectedData::PostRtEvents::appendRT(const PluginPostRtEvent& e) noexcept | void CarlaPlugin::ProtectedData::PostRtEvents::appendRT(const PluginPostRtEvent& e) noexcept | ||||
| { | { | ||||
| // FIXME | |||||
| mutex.lock(); | |||||
| CARLA_SAFE_ASSERT_RETURN(dataPendingMutex.tryLock(),); | |||||
| dataPendingRT.append(e); | dataPendingRT.append(e); | ||||
| mutex.unlock(); | |||||
| dataPendingMutex.unlock(); | |||||
| } | } | ||||
| void CarlaPlugin::ProtectedData::PostRtEvents::trySplice() noexcept | void CarlaPlugin::ProtectedData::PostRtEvents::trySplice() noexcept | ||||
| { | { | ||||
| if (mutex.tryLock()) | |||||
| if (dataMutex.tryLock()) | |||||
| { | { | ||||
| if (dataPendingRT.count() > 0) | if (dataPendingRT.count() > 0) | ||||
| dataPendingRT.moveTo(data, true); | dataPendingRT.moveTo(data, true); | ||||
| mutex.unlock(); | |||||
| dataMutex.unlock(); | |||||
| } | } | ||||
| } | } | ||||
| void CarlaPlugin::ProtectedData::PostRtEvents::clear() noexcept | |||||
| void CarlaPlugin::ProtectedData::PostRtEvents::clearData() noexcept | |||||
| { | { | ||||
| mutex.lock(); | |||||
| const bool tryLockOk(dataMutex.tryLock()); | |||||
| CARLA_SAFE_ASSERT(! tryLockOk); | |||||
| data.clear(); | data.clear(); | ||||
| dataPendingRT.clear(); | |||||
| mutex.unlock(); | |||||
| if (tryLockOk) | |||||
| dataMutex.unlock(); | |||||
| } | } | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -282,19 +282,34 @@ struct CarlaPlugin::ProtectedData { | |||||
| } latency; | } latency; | ||||
| struct PostRtEvents { | |||||
| CarlaMutex mutex; | |||||
| RtLinkedList<PluginPostRtEvent>::Pool dataPool; | |||||
| RtLinkedList<PluginPostRtEvent> data; | |||||
| RtLinkedList<PluginPostRtEvent> dataPendingRT; | |||||
| class PostRtEvents { | |||||
| public: | |||||
| PostRtEvents() noexcept; | PostRtEvents() noexcept; | ||||
| ~PostRtEvents() noexcept; | ~PostRtEvents() noexcept; | ||||
| void appendRT(const PluginPostRtEvent& event) noexcept; | void appendRT(const PluginPostRtEvent& event) noexcept; | ||||
| void trySplice() noexcept; | void trySplice() noexcept; | ||||
| void clear() noexcept; | |||||
| void clearData() noexcept; | |||||
| inline CarlaMutex& getDataMutex() noexcept | |||||
| { | |||||
| return dataMutex; | |||||
| } | |||||
| inline RtLinkedList<PluginPostRtEvent>::Itenerator getDataIterator() const noexcept | |||||
| { | |||||
| return data.begin2(); | |||||
| } | |||||
| private: | |||||
| RtLinkedList<PluginPostRtEvent>::Pool dataPool; | |||||
| RtLinkedList<PluginPostRtEvent> dataPendingRT; | |||||
| RtLinkedList<PluginPostRtEvent> data; | |||||
| CarlaMutex dataMutex; | |||||
| // TESTING for thread-safety, remove later | |||||
| CarlaMutex dataPendingMutex; | |||||
| CARLA_DECLARE_NON_COPY_STRUCT(PostRtEvents) | |||||
| CARLA_DECLARE_NON_COPY_CLASS(PostRtEvents) | |||||
| } postRtEvents; | } postRtEvents; | ||||
| @@ -1,6 +1,6 @@ | |||||
| /* | /* | ||||
| * High-level, real-time safe, templated, C++ doubly-linked list | * High-level, real-time safe, templated, C++ doubly-linked list | ||||
| * Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com> | |||||
| * Copyright (C) 2013-2018 Filipe Coelho <falktx@falktx.com> | |||||
| * | * | ||||
| * This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
| * modify it under the terms of the GNU General Public License as | * modify it under the terms of the GNU General Public License as | ||||
| @@ -107,6 +107,69 @@ public: | |||||
| RtLinkedList(Pool& memPool) noexcept | RtLinkedList(Pool& memPool) noexcept | ||||
| : fMemPool(memPool) {} | : fMemPool(memPool) {} | ||||
| #ifdef STOAT_TEST_BUILD | |||||
| // overridden for stoat | |||||
| bool append(const T& value) noexcept | |||||
| { | |||||
| if (typename AbstractLinkedList<T>::Data* const data = _allocate()) | |||||
| return this->_add_internal(data, value, true, &this->fQueue); | |||||
| return false; | |||||
| } | |||||
| void clear() noexcept | |||||
| { | |||||
| if (this->fCount == 0) | |||||
| return; | |||||
| for (typename AbstractLinkedList<T>::ListHead *entry = this->fQueue.next, *entry2 = entry->next; | |||||
| entry != &this->fQueue; entry = entry2, entry2 = entry->next) | |||||
| { | |||||
| typename AbstractLinkedList<T>::Data* const data = list_entry(entry, typename AbstractLinkedList<T>::Data, siblings); | |||||
| CARLA_SAFE_ASSERT_CONTINUE(data != nullptr); | |||||
| this->_deallocate(data); | |||||
| } | |||||
| this->_init(); | |||||
| } | |||||
| T getFirst(T& fallback, const bool removeObj) noexcept | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(this->fCount > 0, fallback); | |||||
| typename AbstractLinkedList<T>::ListHead* const entry = this->fQueue.next; | |||||
| typename AbstractLinkedList<T>::Data* const data = list_entry(entry, typename AbstractLinkedList<T>::Data, siblings); | |||||
| CARLA_SAFE_ASSERT_RETURN(data != nullptr, fallback); | |||||
| if (! removeObj) | |||||
| return data->value; | |||||
| const T value(data->value); | |||||
| _deleteRT(entry, data); | |||||
| return value; | |||||
| } | |||||
| void _deleteRT(typename AbstractLinkedList<T>::ListHead* const entry, typename AbstractLinkedList<T>::Data* const data) noexcept | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(entry != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(entry->prev != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(entry->next != nullptr,); | |||||
| --this->fCount; | |||||
| entry->next->prev = entry->prev; | |||||
| entry->prev->next = entry->next; | |||||
| entry->next = nullptr; | |||||
| entry->prev = nullptr; | |||||
| _deallocate(data); | |||||
| } | |||||
| #endif | |||||
| bool append_sleepy(const T& value) noexcept | bool append_sleepy(const T& value) noexcept | ||||
| { | { | ||||
| return _add_sleepy(value, true); | return _add_sleepy(value, true); | ||||