diff --git a/libs/image/tiles3/kis_tile_hash_table2.h b/libs/image/tiles3/kis_tile_hash_table2.h index 65c0ab617b..78552d2543 100644 --- a/libs/image/tiles3/kis_tile_hash_table2.h +++ b/libs/image/tiles3/kis_tile_hash_table2.h @@ -1,107 +1,111 @@ #ifndef KIS_TILEHASHTABLE_2_H #define KIS_TILEHASHTABLE_2_H #include "kis_shared.h" #include "kis_shared_ptr.h" #include "3rdparty/lock_free_map/concurrent_map.h" template class KisTileHashTableTraits2 { static constexpr bool isInherited = std::is_convertible::value; Q_STATIC_ASSERT_X(isInherited, "Template must inherit KisShared"); public: typedef T TileType; typedef KisSharedPtr TileTypeSP; typedef KisWeakSharedPtr TileTypeWSP; KisTileHashTableTraits2() : m_rawPointerUsers(0) { m_context = QSBR::instance().createContext(); } ~KisTileHashTableTraits2() { QSBR::instance().destroyContext(m_context); } TileTypeSP insert(qint32 key, TileTypeSP value) { TileTypeSP::ref(&value, value.data()); TileType *result = m_map.assign(key, value.data()); if (result) { MemoryReclaimer *tmp = new MemoryReclaimer(result); QSBR::instance().enqueue(&MemoryReclaimer::destroy, tmp); } return TileTypeSP(result); } TileTypeSP erase(qint32 key) { qint32 currentThreads = m_rawPointerUsers.fetchAndAddRelaxed(1); TileType *result = m_map.erase(key); TileTypeSP ptr(result); if (result) { MemoryReclaimer *tmp = new MemoryReclaimer(result); QSBR::instance().enqueue(&MemoryReclaimer::destroy, tmp); } if (m_rawPointerUsers.testAndSetRelaxed(1, currentThreads)) { QSBR::instance().update(m_context); } m_rawPointerUsers.fetchAndSubRelaxed(1); return ptr; } TileTypeSP get(qint32 key) { m_rawPointerUsers.fetchAndAddRelaxed(1); TileTypeSP result(m_map.get(key)); m_rawPointerUsers.fetchAndSubRelaxed(1); return result; } TileTypeSP getLazy(qint32 key) { m_rawPointerUsers.fetchAndAddRelaxed(1); typename ConcurrentMap::Mutator iter = m_map.insertOrFind(key); - TileTypeSP value(iter.getValue()); - m_rawPointerUsers.fetchAndSubRelaxed(1); - if (!value.data()) { - value.attach(new TileType); + if (!iter.getValue()) { + TileTypeSP value(new TileType); TileTypeSP::ref(&value, value.data()); - iter.exchangeValue(value.data()); + + if (iter.exchangeValue(value.data()) == value.data()) { + MemoryReclaimer *tmp = new MemoryReclaimer(value.data()); + QSBR::instance().enqueue(&MemoryReclaimer::destroy, tmp); + } } - return value; + TileTypeSP result(iter.getValue()); + m_rawPointerUsers.fetchAndSubRelaxed(1); + return result; } private: struct MemoryReclaimer { MemoryReclaimer(TileType *data) : d(data) {} ~MemoryReclaimer() = default; void destroy() { TileTypeSP::deref(reinterpret_cast(this), d); this->MemoryReclaimer::~MemoryReclaimer(); std::free(this); } private: TileType *d; }; ConcurrentMap m_map; QSBR::Context m_context; QAtomicInt m_rawPointerUsers; }; #endif // KIS_TILEHASHTABLE_2_H