summaryrefslogtreecommitdiffstats
path: root/src/core/resources/qresourcemanager_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/resources/qresourcemanager_p.h')
-rw-r--r--src/core/resources/qresourcemanager_p.h213
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