diff --git a/libs/image/3rdparty/lock_free_map/qsbr.h b/libs/image/3rdparty/lock_free_map/qsbr.h index 502356526a..eae7aaaf8f 100644 --- a/libs/image/3rdparty/lock_free_map/qsbr.h +++ b/libs/image/3rdparty/lock_free_map/qsbr.h @@ -1,123 +1,122 @@ /*------------------------------------------------------------------------ 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; KisLocklessStack m_pendingActions; KisLocklessStack m_migrationReclaimActions; - std::atomic_flag m_isProcessing = ATOMIC_FLAG_INIT; void releasePoolSafely(KisLocklessStack *pool, bool force = false) { KisLocklessStack tmp; tmp.mergeFrom(*pool); if (tmp.isEmpty()) return; if (force || tmp.size() > 4096) { while (m_rawPointerUsers.loadAcquire()); Action action; while (tmp.pop(action)) { action(); } } else { if (!m_rawPointerUsers.loadAcquire()) { Action action; while (tmp.pop(action)) { action(); } } else { // push elements back to the source pool->mergeFrom(tmp); } } } 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))); } } void update(bool migrationInProgress) { releasePoolSafely(&m_pendingActions); if (!migrationInProgress) { releasePoolSafely(&m_migrationReclaimActions); } } void flush() { releasePoolSafely(&m_pendingActions, true); releasePoolSafely(&m_migrationReclaimActions, true); } void lockRawPointerAccess() { m_rawPointerUsers.ref(); } void unlockRawPointerAccess() { m_rawPointerUsers.deref(); } }; #endif // QSBR_H