diff options
Diffstat (limited to 'src/core/resources/qresourcemanager_p.h')
-rw-r--r-- | src/core/resources/qresourcemanager_p.h | 213 |
1 files changed, 80 insertions, 133 deletions
diff --git a/src/core/resources/qresourcemanager_p.h b/src/core/resources/qresourcemanager_p.h index 8ddc1c0a4..4cb2a38af 100644 --- a/src/core/resources/qresourcemanager_p.h +++ b/src/core/resources/qresourcemanager_p.h @@ -57,9 +57,9 @@ #include <QtCore/QReadLocker> #include <QtCore/QReadWriteLock> #include <QtCore/QtGlobal> +#include <limits> #include <Qt3DCore/private/qhandle_p.h> -#include <Qt3DCore/private/qhandlemanager_p.h> // Silence complaints about unreferenced local variables in // ArrayAllocatingPolicy::deallocateBuckets() when the compiler @@ -220,15 +220,16 @@ struct Int2Type }; }; -template <typename T, uint INDEXBITS> +template <typename T, uint INDEXBITS = 16> class ArrayAllocatingPolicy { public: + typedef QHandle<T, INDEXBITS> Handle; ArrayAllocatingPolicy() - : m_numBuckets(0) - , m_numConstructed(0) { - reset(); + m_freeList.resize(MaxSize); + for (int i = 0; i < MaxSize; i++) + m_freeList[i] = MaxSize - (i + 1); } ~ArrayAllocatingPolicy() @@ -236,7 +237,7 @@ public: deallocateBuckets(); } - T* allocateResource() + Handle allocateResource() { Q_ASSERT(!m_freeList.isEmpty()); int idx = m_freeList.takeLast(); @@ -245,9 +246,11 @@ public: Q_ASSERT(bucketIdx <= m_numBuckets); if (bucketIdx == m_numBuckets) { m_bucketDataPtrs[bucketIdx] = static_cast<T*>(malloc(sizeof(T) * BucketSize)); + m_counters[bucketIdx] = static_cast<short *>(malloc(sizeof(short) * BucketSize)); // ### memset is only needed as long as we also use this for primitive types (see FrameGraphManager) // ### remove once this is fixed, add a static_assert on T instead - memset((void*) m_bucketDataPtrs[bucketIdx], 0, sizeof(T) * BucketSize); + memset((void *)m_bucketDataPtrs[bucketIdx], 0, sizeof(T) * BucketSize); + memset(m_counters[bucketIdx], 0, sizeof(short) * BucketSize); ++m_numBuckets; } @@ -256,39 +259,47 @@ public: new (m_bucketDataPtrs[bucketIdx] + localIdx) T; ++m_numConstructed; } - - return m_bucketDataPtrs[bucketIdx] + localIdx; + Q_STATIC_ASSERT(Handle::MaxCounter < USHRT_MAX); + Q_ASSERT(m_counters[bucketIdx][localIdx] <= 0); + m_counters[bucketIdx][localIdx] *= -1; + ++m_counters[bucketIdx][localIdx]; + if (m_counters[bucketIdx][localIdx] >= Handle::MaxCounter) + m_counters[bucketIdx][localIdx] = 1; + + return Handle(idx, m_counters[bucketIdx][localIdx]); } - void releaseResource(T *r) + void releaseResource(Handle h) { - // search linearly over buckets to find the index of the resource - // and put it into the free list - for (int bucketIdx = 0; bucketIdx < m_numBuckets; ++bucketIdx) { - const T* firstItem = m_bucketDataPtrs[bucketIdx]; - if (firstItem > r || r >= firstItem + BucketSize) { - // resource is not in this bucket when its pointer address - // is outside the address range spanned by the addresses of - // the first and last items in a bucket - continue; - } + int idx = h.index(); + int bucketIdx = idx / BucketSize; + int localIdx = idx % BucketSize; - // now we found the bucket we can reconstruct the global index - // and put it back into the free list - const int localIdx = static_cast<int>(r - firstItem); - const int idx = bucketIdx * BucketSize + localIdx; - m_freeList.append(idx); - performCleanup(r, Int2Type<QResourceInfo<T>::needsCleanup>()); - break; + Q_ASSERT(h.counter() == static_cast<quint32>(m_counters[bucketIdx][localIdx])); + T *r = m_bucketDataPtrs[bucketIdx] + localIdx; + + m_freeList.append(idx); + m_counters[bucketIdx][localIdx] *= -1; + performCleanup(r, Int2Type<QResourceInfo<T>::needsCleanup>()); + } + + T *data(Handle h/*, bool *ok = 0*/) { + int bucketIdx = h.index() / BucketSize; + int localIdx = h.index() % BucketSize; + + if (h.counter() != static_cast<quint32>(m_counters[bucketIdx][localIdx])) { + return nullptr; } + return m_bucketDataPtrs[bucketIdx] + localIdx; } - void reset() - { - deallocateBuckets(); - m_freeList.resize(MaxSize); - for (int i = 0; i < MaxSize; i++) - m_freeList[i] = MaxSize - (i + 1); + void for_each(std::function<void(T*)> f) { + for (int idx = 0; idx < m_numConstructed; ++idx) { + int bucketIdx = idx / BucketSize; + int localIdx = idx % BucketSize; + T * t = m_bucketDataPtrs[bucketIdx] + localIdx; + f(t); + } } private: @@ -313,66 +324,15 @@ private: while (m_numBuckets > 0) { --m_numBuckets; free(m_bucketDataPtrs[m_numBuckets]); + free(m_counters[m_numBuckets]); } } T* m_bucketDataPtrs[MaxSize / BucketSize]; + short *m_counters[MaxSize / BucketSize]; QVector<int> m_freeList; - int m_numBuckets; - int m_numConstructed; - - void performCleanup(T *r, Int2Type<true>) - { - r->cleanup(); - } - - void performCleanup(T *, Int2Type<false>) - {} - -}; - -template <typename T, uint INDEXBITS> -class ArrayPreallocationPolicy -{ -public: - ArrayPreallocationPolicy() - { - reset(); - } - - T* allocateResource() - { - Q_ASSERT(!m_freeList.isEmpty()); - int idx = m_freeList.last(); - m_freeList.pop_back(); - return m_bucket.data() + idx; - } - - void releaseResource(T *r) - { - Q_ASSERT(m_bucket.data() <= r && r < m_bucket.data() + MaxSize); - int idx = r - m_bucket.data(); - m_freeList.append(idx); - performCleanup(r, Int2Type<QResourceInfo<T>::needsCleanup>()); - *r = T(); - } - - void reset() - { - m_bucket.clear(); - m_bucket.resize(MaxSize); - m_freeList.resize(MaxSize); - for (int i = 0; i < MaxSize; i++) - m_freeList[i] = MaxSize - (i + 1); - } - -private: - enum { - MaxSize = 1 << INDEXBITS - }; - - QVector<T> m_bucket; - QVector<int> m_freeList; + int m_numBuckets = 0; + int m_numConstructed = 0; void performCleanup(T *r, Int2Type<true>) { @@ -386,29 +346,29 @@ private: #ifndef QT_NO_DEBUG_STREAM template <typename ValueType, typename KeyType, uint INDEXBITS, - template <typename, uint> class AllocatingPolicy, template <class> class LockingPolicy > class QResourceManager; template <typename ValueType, typename KeyType, uint INDEXBITS = 16, - template <typename, uint> class AllocatingPolicy = ArrayAllocatingPolicy, template <class> class LockingPolicy = NonLockingPolicy > -QDebug operator<<(QDebug dbg, const QResourceManager<ValueType, KeyType, INDEXBITS, AllocatingPolicy, LockingPolicy> &manager); +QDebug operator<<(QDebug dbg, const QResourceManager<ValueType, KeyType, INDEXBITS, LockingPolicy> &manager); #endif template <typename ValueType, typename KeyType, uint INDEXBITS = 16, - template <typename, uint> class AllocatingPolicy = ArrayAllocatingPolicy, template <class> class LockingPolicy = NonLockingPolicy > class QResourceManager - : public AllocatingPolicy<ValueType, INDEXBITS> - , public LockingPolicy< QResourceManager<ValueType, KeyType, INDEXBITS, AllocatingPolicy, LockingPolicy> > + : public ArrayAllocatingPolicy<ValueType, INDEXBITS> + , public LockingPolicy< QResourceManager<ValueType, KeyType, INDEXBITS, LockingPolicy> > { public: + typedef ArrayAllocatingPolicy<ValueType, INDEXBITS> Allocator; + typedef QHandle<ValueType, INDEXBITS> Handle; + QResourceManager() : - AllocatingPolicy<ValueType, INDEXBITS>(), + Allocator(), m_maxSize((1 << INDEXBITS) - 1) { } @@ -416,52 +376,43 @@ public: ~QResourceManager() {} - QHandle<ValueType, INDEXBITS> acquire() + Handle acquire() { typename LockingPolicy<QResourceManager>::WriteLocker lock(this); - QHandle<ValueType, INDEXBITS> handle = m_handleManager.acquire(AllocatingPolicy<ValueType, INDEXBITS>::allocateResource()); + Handle handle = Allocator::allocateResource(); m_activeHandles.push_back(handle); return handle; } - ValueType* data(const QHandle<ValueType, INDEXBITS> &handle) + ValueType* data(const Handle &handle) { typename LockingPolicy<QResourceManager>::ReadLocker lock(this); - ValueType* d = m_handleManager.data(handle); - return d; + return Allocator::data(handle); } - void release(const QHandle<ValueType, INDEXBITS> &handle) + void release(const Handle &handle) { typename LockingPolicy<QResourceManager>::WriteLocker lock(this); releaseLocked(handle); } - void reset() - { - typename LockingPolicy<QResourceManager>::WriteLocker lock(this); - m_handleManager.reset(); - m_activeHandles.clear(); - AllocatingPolicy<ValueType, INDEXBITS>::reset(); - } - bool contains(const KeyType &id) const { typename LockingPolicy<QResourceManager>::ReadLocker lock(this); return m_keyToHandleMap.contains(id); } - QHandle<ValueType, INDEXBITS> getOrAcquireHandle(const KeyType &id) + Handle getOrAcquireHandle(const KeyType &id) { typename LockingPolicy<QResourceManager>::ReadLocker lock(this); - QHandle<ValueType, INDEXBITS> handle = m_keyToHandleMap.value(id); + Handle handle = m_keyToHandleMap.value(id); if (handle.isNull()) { lock.unlock(); typename LockingPolicy<QResourceManager>::WriteLocker writeLock(this); // Test that the handle hasn't been set (in the meantime between the read unlock and the write lock) - QHandle<ValueType, INDEXBITS> &handleToSet = m_keyToHandleMap[id]; + Handle &handleToSet = m_keyToHandleMap[id]; if (handleToSet.isNull()) { - handleToSet = m_handleManager.acquire(AllocatingPolicy<ValueType, INDEXBITS>::allocateResource()); + handleToSet = Allocator::allocateResource(); m_activeHandles.push_back(handleToSet); } return handleToSet; @@ -469,7 +420,7 @@ public: return handle; } - QHandle<ValueType, INDEXBITS> lookupHandle(const KeyType &id) + Handle lookupHandle(const KeyType &id) { typename LockingPolicy<QResourceManager>::ReadLocker lock(this); return m_keyToHandleMap.value(id); @@ -480,58 +431,54 @@ public: ValueType* ret = nullptr; { typename LockingPolicy<QResourceManager>::ReadLocker lock(this); - QHandle<ValueType, INDEXBITS> handle = m_keyToHandleMap.value(id); + Handle handle = m_keyToHandleMap.value(id); if (!handle.isNull()) - ret = m_handleManager.data(handle); + ret = Allocator::data(handle); } return ret; } ValueType *getOrCreateResource(const KeyType &id) { - const QHandle<ValueType, INDEXBITS> handle = getOrAcquireHandle(id); + const Handle handle = getOrAcquireHandle(id); typename LockingPolicy<QResourceManager>::ReadLocker lock(this); - return m_handleManager.data(handle); + return Allocator::data(handle); } void releaseResource(const KeyType &id) { typename LockingPolicy<QResourceManager>::WriteLocker lock(this); - QHandle<ValueType, INDEXBITS> handle = m_keyToHandleMap.take(id); + Handle handle = m_keyToHandleMap.take(id); if (!handle.isNull()) releaseLocked(handle); } int maximumSize() const { return m_maxSize; } - int count() const Q_DECL_NOEXCEPT { return m_handleManager.activeEntries(); } + int count() const Q_DECL_NOEXCEPT { return m_activeHandles.size(); } - inline QVector<QHandle<ValueType, INDEXBITS> > activeHandles() const Q_DECL_NOEXCEPT { return m_activeHandles; } + inline QVector<Handle > activeHandles() const Q_DECL_NOEXCEPT { return m_activeHandles; } protected: - QHandleManager<ValueType, INDEXBITS> m_handleManager; - QHash<KeyType, QHandle<ValueType, INDEXBITS> > m_keyToHandleMap; - QVector<QHandle<ValueType, INDEXBITS> > m_activeHandles; + QHash<KeyType, Handle > m_keyToHandleMap; + QVector<Handle > m_activeHandles; const int m_maxSize; private: - void releaseLocked(const QHandle<ValueType, INDEXBITS> &handle) + void releaseLocked(const Handle &handle) { - ValueType *val = m_handleManager.data(handle); - m_handleManager.release(handle); m_activeHandles.removeOne(handle); - AllocatingPolicy<ValueType, INDEXBITS>::releaseResource(val); + Allocator::releaseResource(handle); } - friend QDebug operator<< <>(QDebug dbg, const QResourceManager<ValueType, KeyType, INDEXBITS, AllocatingPolicy, LockingPolicy> &manager); + friend QDebug operator<< <>(QDebug dbg, const QResourceManager<ValueType, KeyType, INDEXBITS, LockingPolicy> &manager); }; #ifndef QT_NO_DEBUG_STREAM template <typename ValueType, typename KeyType, uint INDEXBITS, - template <typename, uint> class AllocatingPolicy, template <class> class LockingPolicy > -QDebug operator<<(QDebug dbg, const QResourceManager<ValueType, KeyType, INDEXBITS, AllocatingPolicy, LockingPolicy> &manager) +QDebug operator<<(QDebug dbg, const QResourceManager<ValueType, KeyType, INDEXBITS, LockingPolicy> &manager) { QDebugStateSaver saver(dbg); dbg << "Contains" << manager.count() << "items" << "of a maximum" << manager.maximumSize() << endl; @@ -541,8 +488,8 @@ QDebug operator<<(QDebug dbg, const QResourceManager<ValueType, KeyType, INDEXBI for (auto it = manager.m_keyToHandleMap.cbegin(); it != end; ++it) dbg << "QNodeId =" << it.key() << "Handle =" << it.value() << endl; - dbg << "Resources:" << endl; - dbg << manager.m_handleManager; +// dbg << "Resources:" << endl; +// dbg << manager.m_handleManager; return dbg; } #endif |