diff --git a/libs/image/3rdparty/lock_free_map/qsbr.h b/libs/image/3rdparty/lock_free_map/qsbr.h index d821cd3b10..cc711987db 100644 --- a/libs/image/3rdparty/lock_free_map/qsbr.h +++ b/libs/image/3rdparty/lock_free_map/qsbr.h @@ -1,131 +1,123 @@ /*------------------------------------------------------------------------ Junction: Concurrent data structures in C++ Copyright (c) 2016 Jeff Preshing Distributed under the Simplified BSD License. Original location: https://github.com/preshing/junction This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file for more information. ------------------------------------------------------------------------*/ #ifndef QSBR_H #define QSBR_H #include #include #include #include #define CALL_MEMBER(obj, pmf) ((obj).*(pmf)) class QSBR { private: struct Action { void (*func)(void*); quint64 param[4]; // Size limit found experimentally. Verified by assert below. Action() = default; Action(void (*f)(void*), void* p, quint64 paramSize) : func(f) { KIS_ASSERT(paramSize <= sizeof(param)); // Verify size limit. memcpy(¶m, p, paramSize); } void operator()() { func(¶m); } }; QAtomicInt m_rawPointerUsers; - QAtomicInt m_poolSize; KisLocklessStack m_pendingActions; KisLocklessStack m_migrationReclaimActions; std::atomic_flag m_isProcessing = ATOMIC_FLAG_INIT; void releasePoolSafely(KisLocklessStack *pool) { Action action; while (pool->pop(action)) { action(); } } public: template void enqueue(void (T::*pmf)(), T* target, bool migration = false) { struct Closure { void (T::*pmf)(); T* target; static void thunk(void* param) { Closure* self = (Closure*) param; CALL_MEMBER(*self->target, self->pmf)(); } }; - Closure closure = {pmf, target}; if (migration) { m_migrationReclaimActions.push(Action(Closure::thunk, &closure, sizeof(closure))); } else { m_pendingActions.push(Action(Closure::thunk, &closure, sizeof(closure))); } - - m_poolSize.ref(); } - void update(bool migration) + void update(bool migrationInProgress) { if (m_rawPointerUsers.testAndSetAcquire(0, 1)) { releasePoolSafely(&m_pendingActions); - m_poolSize.store(0); - if (!migration) { + if (!migrationInProgress) { releasePoolSafely(&m_migrationReclaimActions); } m_rawPointerUsers.deref(); - } else if (m_poolSize > 4098) { + } else if (m_pendingActions.size() > 4098) { // TODO: make pool size limit configurable! while (!m_rawPointerUsers.testAndSetAcquire(0, 1)); releasePoolSafely(&m_pendingActions); - m_poolSize.store(0); m_rawPointerUsers.deref(); } } void flush() { while (!m_rawPointerUsers.testAndSetAcquire(0, 1)); releasePoolSafely(&m_pendingActions); - m_poolSize.store(0); - releasePoolSafely(&m_migrationReclaimActions); m_rawPointerUsers.deref(); } void lockRawPointerAccess() { m_rawPointerUsers.ref(); } void unlockRawPointerAccess() { m_rawPointerUsers.deref(); } }; #endif // QSBR_H