@@ -216,3 +216,4 @@ LinuxSampler::InstrumentManager::LoadInstrumentInBackground | |||
llround | |||
llabs | |||
clock_gettime | |||
RtLinkedList$vtable3 |
@@ -1864,9 +1864,9 @@ void CarlaPlugin::idle() | |||
#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)); | |||
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 | |||
@@ -501,40 +501,49 @@ void CarlaPlugin::ProtectedData::Latency::recreateBuffers(const uint32_t newChan | |||
// ProtectedData::PostRtEvents | |||
CarlaPlugin::ProtectedData::PostRtEvents::PostRtEvents() noexcept | |||
: mutex(), | |||
dataPool(128, 128), | |||
: dataPool(128, 128), | |||
dataPendingRT(dataPool), | |||
data(dataPool), | |||
dataPendingRT(dataPool) {} | |||
dataMutex(), | |||
dataPendingMutex() {} | |||
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 | |||
{ | |||
// FIXME | |||
mutex.lock(); | |||
CARLA_SAFE_ASSERT_RETURN(dataPendingMutex.tryLock(),); | |||
dataPendingRT.append(e); | |||
mutex.unlock(); | |||
dataPendingMutex.unlock(); | |||
} | |||
void CarlaPlugin::ProtectedData::PostRtEvents::trySplice() noexcept | |||
{ | |||
if (mutex.tryLock()) | |||
if (dataMutex.tryLock()) | |||
{ | |||
if (dataPendingRT.count() > 0) | |||
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(); | |||
dataPendingRT.clear(); | |||
mutex.unlock(); | |||
if (tryLockOk) | |||
dataMutex.unlock(); | |||
} | |||
// ----------------------------------------------------------------------- | |||
@@ -282,19 +282,34 @@ struct CarlaPlugin::ProtectedData { | |||
} latency; | |||
struct PostRtEvents { | |||
CarlaMutex mutex; | |||
RtLinkedList<PluginPostRtEvent>::Pool dataPool; | |||
RtLinkedList<PluginPostRtEvent> data; | |||
RtLinkedList<PluginPostRtEvent> dataPendingRT; | |||
class PostRtEvents { | |||
public: | |||
PostRtEvents() noexcept; | |||
~PostRtEvents() noexcept; | |||
void appendRT(const PluginPostRtEvent& event) 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; | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* 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 | |||
* modify it under the terms of the GNU General Public License as | |||
@@ -107,6 +107,69 @@ public: | |||
RtLinkedList(Pool& memPool) noexcept | |||
: 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 | |||
{ | |||
return _add_sleepy(value, true); | |||