mirror of
https://github.com/beefytech/Beef.git
synced 2025-07-04 23:36:00 +02:00
Improved hotswapping with extension modules
This commit is contained in:
parent
769036584a
commit
fd4fd43ce3
19 changed files with 836 additions and 232 deletions
|
@ -4,16 +4,16 @@
|
|||
|
||||
NS_BF_BEGIN;
|
||||
|
||||
template <typename T>
|
||||
class AllocatorCLib
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
T* allocate(intptr count)
|
||||
{
|
||||
return (T*)malloc(sizeof(T) * count);
|
||||
}
|
||||
|
||||
void deallocate(T* ptr)
|
||||
void deallocate(void* ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
@ -27,9 +27,14 @@ public:
|
|||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
bool deallocateAll()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename TAlloc = AllocatorCLib<T> >
|
||||
template <typename T, typename TAlloc = AllocatorCLib >
|
||||
class ArrayBase : public TAlloc
|
||||
{
|
||||
public:
|
||||
|
@ -445,7 +450,7 @@ protected:
|
|||
|
||||
void SetBufferSize(intptr newSize)
|
||||
{
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (this->mSize > 0)
|
||||
|
@ -625,7 +630,7 @@ public:
|
|||
{
|
||||
intptr newSize = this->mAllocSize + this->mAllocSize / 2 + 1;
|
||||
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (idx > 0) // Copy left of idx
|
||||
|
@ -653,7 +658,7 @@ public:
|
|||
{
|
||||
intptr newSize = BF_MAX(this->mSize + size, this->mAllocSize + this->mAllocSize / 2 + 1);
|
||||
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (idx > 0) // Copy left of idx
|
||||
|
@ -682,7 +687,7 @@ public:
|
|||
{
|
||||
intptr newSize = BF_MAX(this->mSize + count, this->mAllocSize + this->mAllocSize / 2 + 1);
|
||||
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (idx > 0) // Copy left of idx
|
||||
|
@ -764,7 +769,7 @@ public:
|
|||
protected:
|
||||
void SetBufferSize(intptr newSize)
|
||||
{
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (this->mSize > 0)
|
||||
|
@ -928,7 +933,7 @@ public:
|
|||
{
|
||||
intptr newSize = this->mAllocSize + this->mAllocSize / 2 + 1;
|
||||
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (idx > 0) // Copy left of idx
|
||||
|
@ -956,7 +961,7 @@ public:
|
|||
{
|
||||
intptr newSize = BF_MAX(this->mSize + size, this->mAllocSize + this->mAllocSize / 2 + 1);
|
||||
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (idx > 0) // Copy left of idx
|
||||
|
@ -984,7 +989,7 @@ public:
|
|||
{
|
||||
intptr newSize = BF_MAX(this->mSize + size, this->mAllocSize + this->mAllocSize / 2 + 1);
|
||||
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (idx > 0) // Copy left of idx
|
||||
|
@ -1102,7 +1107,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T, typename TAlloc = AllocatorCLib<T> >
|
||||
template <typename T, typename TAlloc = AllocatorCLib >
|
||||
class Array : public ArrayImpl<T, TAlloc, std::is_pod<T>::value>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -255,23 +255,24 @@ class BumpAllocator : public BumpAllocatorT<0x2000>
|
|||
|
||||
};
|
||||
|
||||
template <typename T, int ALLOC_SIZE = 0x2000>
|
||||
class AllocatorBump
|
||||
template <int ALLOC_SIZE = 0x2000>
|
||||
class AllocatorBumpT
|
||||
{
|
||||
public:
|
||||
BumpAllocatorT<ALLOC_SIZE>* mAlloc;
|
||||
|
||||
AllocatorBump()
|
||||
AllocatorBumpT()
|
||||
{
|
||||
mAlloc = NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* allocate(intptr count)
|
||||
{
|
||||
return (T*)mAlloc->AllocBytes((int)(sizeof(T) * count), alignof(T));
|
||||
}
|
||||
|
||||
void deallocate(T* ptr)
|
||||
void deallocate(void* ptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -286,26 +287,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <int ALLOC_SIZE = 0x2000>
|
||||
class RawAllocatorBump
|
||||
class AllocatorBump : public AllocatorBumpT<0x2000>
|
||||
{
|
||||
public:
|
||||
BumpAllocatorT<ALLOC_SIZE>* mAlloc;
|
||||
|
||||
RawAllocatorBump()
|
||||
{
|
||||
mAlloc = NULL;
|
||||
}
|
||||
|
||||
void* rawAllocate(intptr size)
|
||||
{
|
||||
return mAlloc->AllocBytes(size, 16);
|
||||
}
|
||||
|
||||
void rawDeallocate(void* ptr)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
NS_BF_END
|
||||
|
|
|
@ -8,7 +8,7 @@ NS_BF_BEGIN;
|
|||
#define DEQUE_IDX(i) (this->mVals[((i) + this->mOffset) % this->mAllocSize])
|
||||
#define DEQUE_IDX_ON(arr, i) ((arr).mVals[((i) + (arr).mOffset) % (arr).mAllocSize])
|
||||
|
||||
template <typename T, typename TAlloc = AllocatorCLib<T> >
|
||||
template <typename T, typename TAlloc = AllocatorCLib >
|
||||
class DequeBase : public TAlloc
|
||||
{
|
||||
public:
|
||||
|
@ -370,7 +370,7 @@ protected:
|
|||
|
||||
void Grow(intptr newSize)
|
||||
{
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (this->mSize > 0)
|
||||
|
@ -707,7 +707,7 @@ class DequeImpl<T, TAlloc, true> : public DequeBase<T, TAlloc>
|
|||
protected:
|
||||
void Grow(intptr newSize)
|
||||
{
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (this->mSize > 0)
|
||||
|
@ -1043,7 +1043,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T, typename TAlloc = AllocatorCLib<T> >
|
||||
template <typename T, typename TAlloc = AllocatorCLib >
|
||||
class Deque : public DequeImpl<T, TAlloc, std::is_pod<T>::value>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -9,7 +9,7 @@ NS_BF_BEGIN;
|
|||
|
||||
#ifdef NEW_DICTIONAY
|
||||
|
||||
template <typename TKey, typename TValue, typename TAlloc = AllocatorCLib<TKey> >
|
||||
template <typename TKey, typename TValue, typename TAlloc = AllocatorCLib >
|
||||
class Dictionary : public TAlloc
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
NS_BF_BEGIN;
|
||||
|
||||
template <typename TKey, typename TAlloc = AllocatorCLib<TKey> >
|
||||
template <typename TKey, typename TAlloc = AllocatorCLib >
|
||||
class HashSet : public TAlloc
|
||||
{
|
||||
public:
|
||||
|
|
523
BeefySysLib/util/MultiDictionary.h
Normal file
523
BeefySysLib/util/MultiDictionary.h
Normal file
|
@ -0,0 +1,523 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Common.h"
|
||||
#include "Array.h"
|
||||
|
||||
NS_BF_BEGIN;
|
||||
|
||||
struct MultiDictionaryFuncs : AllocatorCLib
|
||||
{
|
||||
template <typename T>
|
||||
size_t GetHash(const T& value)
|
||||
{
|
||||
return BeefHash<T>()(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Matches(const T& lhs, const T& rhs)
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TKey, typename TValue, typename TFuncs = MultiDictionaryFuncs>
|
||||
class MultiDictionary : public TFuncs
|
||||
{
|
||||
public:
|
||||
struct Entry
|
||||
{
|
||||
TKey mKey;
|
||||
TValue mValue;
|
||||
int mNext;
|
||||
int mHashCode;
|
||||
};
|
||||
|
||||
struct EntryRef
|
||||
{
|
||||
public:
|
||||
MultiDictionary* mSet;
|
||||
int mIndex;
|
||||
|
||||
public:
|
||||
EntryRef()
|
||||
{
|
||||
mSet = NULL;
|
||||
mIndex = -1;
|
||||
}
|
||||
|
||||
EntryRef(MultiDictionary* set, int index)
|
||||
{
|
||||
mSet = set;
|
||||
mIndex = index;
|
||||
}
|
||||
|
||||
Entry* operator*()
|
||||
{
|
||||
return &this->mSet->mEntries[this->mIndex];
|
||||
}
|
||||
|
||||
Entry* operator->()
|
||||
{
|
||||
return &this->mSet->mEntries[this->mIndex];
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return this->mIndex != -1;
|
||||
}
|
||||
};
|
||||
|
||||
struct Iterator
|
||||
{
|
||||
public:
|
||||
MultiDictionary* mSet;
|
||||
int mCurEntry;
|
||||
int mCurBucket;
|
||||
|
||||
public:
|
||||
Iterator(MultiDictionary* set)
|
||||
{
|
||||
this->mSet = set;
|
||||
this->mCurBucket = 0;
|
||||
this->mCurEntry = -1;
|
||||
}
|
||||
|
||||
Iterator& operator++()
|
||||
{
|
||||
if (this->mCurEntry != -1)
|
||||
{
|
||||
this->mCurEntry = this->mSet->mEntries[this->mCurEntry].mNext;
|
||||
if (this->mCurEntry != -1)
|
||||
return *this;
|
||||
this->mCurBucket++;
|
||||
}
|
||||
|
||||
if (mSet->mHashHeads == NULL)
|
||||
{
|
||||
this->mCurBucket = this->mSet->mHashSize;
|
||||
return *this; // At end
|
||||
}
|
||||
|
||||
while (this->mCurBucket < mSet->mHashSize)
|
||||
{
|
||||
this->mCurEntry = this->mSet->mHashHeads[mCurBucket];
|
||||
if (this->mCurEntry != -1)
|
||||
return *this;
|
||||
this->mCurBucket++;
|
||||
}
|
||||
|
||||
return *this; // At end
|
||||
}
|
||||
|
||||
TKey GetKey()
|
||||
{
|
||||
return this->mSet->mEntries[this->mCurEntry].mKey;
|
||||
}
|
||||
|
||||
TValue GetValue()
|
||||
{
|
||||
return this->mSet->mEntries[this->mCurEntry].mValue;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator& itr) const
|
||||
{
|
||||
return ((itr.mCurEntry != this->mCurEntry) || (itr.mCurBucket != this->mCurBucket));
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return this->mCurEntry != -1;
|
||||
}
|
||||
|
||||
void MoveToNextHashMatch()
|
||||
{
|
||||
int wantHash = this->mSet->mEntries[this->mCurEntry].mHashCode;
|
||||
do
|
||||
{
|
||||
this->mCurEntry = this->mSet->mEntries[this->mCurEntry].mNext;
|
||||
} while ((this->mCurEntry != -1) && (this->mSet->mEntries[this->mCurEntry].mHashCode != wantHash));
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
int GetPrimeish(int min)
|
||||
{
|
||||
// This is a minimal effort to help address-aligned dataa
|
||||
return (min | 1);
|
||||
}
|
||||
|
||||
int ExpandSize(int oldSize)
|
||||
{
|
||||
int newSize = 2 * oldSize;
|
||||
|
||||
// Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow.
|
||||
// Note that this check works even when mAllocSize overflowed thanks to the (uint) cast
|
||||
/*if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize)
|
||||
{
|
||||
Contract.Assert( MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength");
|
||||
return MaxPrimeArrayLength;
|
||||
}*/
|
||||
|
||||
return GetPrimeish(newSize);
|
||||
}
|
||||
|
||||
void ResizeEntries()
|
||||
{
|
||||
ResizeEntries(ExpandSize(mCount));
|
||||
}
|
||||
|
||||
void ResizeEntries(int newSize)
|
||||
{
|
||||
BF_ASSERT(newSize >= mAllocSize);
|
||||
Entry* newEntries = TFuncs::allocate<Entry>(newSize);
|
||||
|
||||
for (int i = 0; i < mCount; i++)
|
||||
{
|
||||
auto& newEntry = newEntries[i];
|
||||
auto& oldEntry = mEntries[i];
|
||||
newEntry.mHashCode = oldEntry.mHashCode;
|
||||
newEntry.mNext = oldEntry.mNext;
|
||||
new (&newEntry.mKey) TKey(std::move(*(TKey*)&oldEntry.mKey));
|
||||
new (&newEntry.mValue) TValue(std::move(*(TValue*)&oldEntry.mValue));
|
||||
}
|
||||
for (int i = mCount; i < newSize; i++)
|
||||
{
|
||||
newEntries[i].mHashCode = -1;
|
||||
}
|
||||
|
||||
TFuncs::deallocate(mEntries);
|
||||
|
||||
mEntries = newEntries;
|
||||
mAllocSize = (int)newSize;
|
||||
}
|
||||
|
||||
void FreeIdx(int entryIdx)
|
||||
{
|
||||
this->mEntries[entryIdx].mNext = this->mFreeList;
|
||||
this->mFreeList = entryIdx;
|
||||
this->mFreeCount++;
|
||||
}
|
||||
|
||||
int AllocEntry()
|
||||
{
|
||||
int index;
|
||||
if (this->mFreeCount > 0)
|
||||
{
|
||||
index = this->mFreeList;
|
||||
this->mFreeList = this->mEntries[index].mNext;
|
||||
this->mFreeCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->mCount == this->mAllocSize)
|
||||
ResizeEntries();
|
||||
index = mCount;
|
||||
this->mCount++;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
public:
|
||||
int* mHashHeads;
|
||||
int mAllocSize;
|
||||
Entry* mEntries;
|
||||
int mFreeList;
|
||||
int mFreeCount;
|
||||
|
||||
static const int cDefaultHashSize = 17;
|
||||
int mHashSize;
|
||||
int mCount;
|
||||
|
||||
MultiDictionary()
|
||||
{
|
||||
this->mHashHeads = NULL;
|
||||
this->mHashSize = cDefaultHashSize;
|
||||
this->mEntries = NULL;
|
||||
this->mAllocSize = 0;
|
||||
this->mCount = 0;
|
||||
this->mFreeList = -1;
|
||||
this->mFreeCount = 0;
|
||||
}
|
||||
|
||||
~MultiDictionary()
|
||||
{
|
||||
this->Clear();
|
||||
}
|
||||
|
||||
void EnsureFreeCount(int wantFreeCount)
|
||||
{
|
||||
int freeCount = mFreeCount + (mAllocSize - mCount);
|
||||
if (freeCount >= wantFreeCount)
|
||||
return;
|
||||
ResizeEntries(BF_MAX(ExpandSize(mCount), mAllocSize + wantFreeCount - freeCount));
|
||||
}
|
||||
|
||||
int GetCount() const
|
||||
{
|
||||
return mCount - mFreeCount;
|
||||
}
|
||||
|
||||
int size() const
|
||||
{
|
||||
return mCount - mFreeCount;
|
||||
}
|
||||
|
||||
EntryRef AddRaw(int hash)
|
||||
{
|
||||
if (this->mHashHeads == NULL)
|
||||
{
|
||||
this->mHashHeads = TFuncs::allocate<int>(mHashSize);
|
||||
memset(this->mHashHeads, -1, sizeof(int) * mHashSize);
|
||||
}
|
||||
|
||||
int index = AllocEntry();
|
||||
int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
|
||||
int headEntry = this->mHashHeads[hashIdx];
|
||||
|
||||
Entry* newEntry = &mEntries[index];
|
||||
newEntry->mValue = T();
|
||||
newEntry->mNext = headEntry;
|
||||
newEntry->mHashCode = hash;
|
||||
|
||||
mHashHeads[hashIdx] = index;
|
||||
|
||||
return EntryRef(this, index);
|
||||
}
|
||||
|
||||
void Add(TKey key, TValue value)
|
||||
{
|
||||
if (this->mHashHeads == NULL)
|
||||
{
|
||||
this->mHashHeads = TFuncs::allocate<int>(mHashSize);
|
||||
memset(this->mHashHeads, -1, sizeof(int) * mHashSize);
|
||||
}
|
||||
|
||||
int index = AllocEntry();
|
||||
int hash = TFuncs::GetHash(key);
|
||||
int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
|
||||
int headEntry = this->mHashHeads[hashIdx];
|
||||
|
||||
Entry* newEntry = &mEntries[index];
|
||||
newEntry->mKey = key;
|
||||
newEntry->mValue = value;
|
||||
newEntry->mNext = headEntry;
|
||||
newEntry->mHashCode = hash;
|
||||
|
||||
mHashHeads[hashIdx] = index;
|
||||
}
|
||||
|
||||
void AddAfter(TKey key, TValue value, Entry* afterEntry)
|
||||
{
|
||||
int hash = TFuncs::GetHash(key);
|
||||
int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
|
||||
BF_ASSERT(hash == afterEntry->mHashCode);
|
||||
|
||||
int index = AllocEntry();
|
||||
Entry* newEntry = &mEntries[index];
|
||||
newEntry->mKey = key;
|
||||
newEntry->mValue = value;
|
||||
newEntry->mNext = afterEntry->mNext;
|
||||
newEntry->mHashCode = hash;
|
||||
|
||||
afterEntry->mNext = index;
|
||||
}
|
||||
|
||||
void Rehash(int newHashSize)
|
||||
{
|
||||
auto newHashHeads = TFuncs::allocate<int>(newHashSize);
|
||||
memset(newHashHeads, -1, sizeof(int) * newHashSize);
|
||||
|
||||
if (mHashHeads != NULL)
|
||||
{
|
||||
SizedArray<int, 1024> entryList;
|
||||
for (int hashIdx = 0; hashIdx < mHashSize; hashIdx++)
|
||||
{
|
||||
int checkEntryIdx = mHashHeads[hashIdx];
|
||||
if (checkEntryIdx != -1)
|
||||
{
|
||||
// We want to keep elements with equal hashes in their insert order so we need to
|
||||
// iterate through the linked list in reverse
|
||||
entryList.Clear();
|
||||
|
||||
while (checkEntryIdx != -1)
|
||||
{
|
||||
entryList.Add(checkEntryIdx);
|
||||
checkEntryIdx = mEntries[checkEntryIdx].mNext;
|
||||
}
|
||||
|
||||
for (int i = (int)entryList.mSize - 1; i >= 0; i--)
|
||||
{
|
||||
int checkEntryIdx = entryList[i];
|
||||
auto checkEntry = &mEntries[checkEntryIdx];
|
||||
int newHashIdx = (checkEntry->mHashCode & 0x7FFFFFFF) % newHashSize;
|
||||
checkEntry->mNext = newHashHeads[newHashIdx];
|
||||
newHashHeads[newHashIdx] = checkEntryIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TFuncs::deallocate(mHashHeads);
|
||||
}
|
||||
mHashHeads = newHashHeads;
|
||||
mHashSize = newHashSize;
|
||||
}
|
||||
|
||||
void CheckRehash()
|
||||
{
|
||||
// Make the lookup load reasonable
|
||||
if (mHashSize < mCount)
|
||||
{
|
||||
this->Rehash(BF_MAX(mCount, (int)(mHashSize * 1.5f)) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
bool TryGet(const TKey& key, TKey* outKey, TValue* outValue)
|
||||
{
|
||||
if (mHashHeads == NULL)
|
||||
return false;
|
||||
|
||||
this->CheckRehash();
|
||||
|
||||
int hash = TFuncs::GetHash(key);
|
||||
int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
|
||||
int checkEntryIdx = this->mHashHeads[hashIdx];
|
||||
while (checkEntryIdx != -1)
|
||||
{
|
||||
Entry* checkEntry = &mEntries[checkEntryIdx];
|
||||
if ((checkEntry->mHashCode == hash) && (TFuncs::Matches(key, checkEntry->mKey)))
|
||||
{
|
||||
if (outKey != NULL)
|
||||
*outKey = checkEntry->mKey;
|
||||
if (outValue != NULL)
|
||||
*outValue = checkEntry->mValue;
|
||||
return true;
|
||||
}
|
||||
checkEntryIdx = checkEntry->mNext;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
Iterator TryGet(const TKey& key)
|
||||
{
|
||||
if (mHashHeads == NULL)
|
||||
return end();
|
||||
|
||||
this->CheckRehash();
|
||||
|
||||
int hash = TFuncs::GetHash(key);
|
||||
int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
|
||||
int checkEntryIdx = this->mHashHeads[hashIdx];
|
||||
while (checkEntryIdx != -1)
|
||||
{
|
||||
auto checkEntry = &this->mEntries[checkEntryIdx];
|
||||
if ((checkEntry->mHashCode == hash) && (TFuncs::Matches(key, checkEntry->mKey)))
|
||||
{
|
||||
Iterator itr(this);
|
||||
itr.mCurEntry = checkEntryIdx;
|
||||
itr.mCurBucket = hashIdx;
|
||||
return itr;
|
||||
}
|
||||
checkEntryIdx = checkEntry->mNext;
|
||||
}
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
bool Remove(const TKey& key)
|
||||
{
|
||||
if (mHashHeads == NULL)
|
||||
return false;
|
||||
|
||||
this->CheckRehash();
|
||||
|
||||
int hash = TFuncs::GetHash(key);
|
||||
int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
|
||||
|
||||
int* srcCheckEntryPtr = &this->mHashHeads[hashIdx];
|
||||
int checkEntryIdx = *srcCheckEntryPtr;
|
||||
while (checkEntryIdx != -1)
|
||||
{
|
||||
auto checkEntry = &mEntries[checkEntryIdx];
|
||||
if ((checkEntry->mHashCode == hash) && (TFuncs::Matches(key, checkEntry->mKey)))
|
||||
{
|
||||
*srcCheckEntryPtr = checkEntry->mNext;
|
||||
FreeIdx(checkEntryIdx);
|
||||
return true;
|
||||
}
|
||||
srcCheckEntryPtr = &checkEntry->mNext;
|
||||
checkEntryIdx = checkEntry->mNext;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator Erase(const Iterator& itr)
|
||||
{
|
||||
Iterator next = itr;
|
||||
++next;
|
||||
|
||||
bool found = false;
|
||||
|
||||
auto entryIdx = itr.mCurEntry;
|
||||
auto entry = &mEntries[entryIdx];
|
||||
int hashIdx = (entry->mHashCode & 0x7FFFFFFF) % this->mHashSize;
|
||||
|
||||
int* srcCheckEntryPtr = &this->mHashHeads[hashIdx];
|
||||
int checkEntryIdx = *srcCheckEntryPtr;
|
||||
while (checkEntryIdx != -1)
|
||||
{
|
||||
auto checkEntry = &mEntries[checkEntryIdx];
|
||||
if (checkEntryIdx == itr.mCurEntry)
|
||||
{
|
||||
*srcCheckEntryPtr = checkEntry->mNext;
|
||||
found = true;
|
||||
}
|
||||
srcCheckEntryPtr = &checkEntry->mNext;
|
||||
checkEntryIdx = checkEntry->mNext;
|
||||
}
|
||||
|
||||
BF_ASSERT(found);
|
||||
FreeIdx(entryIdx);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
if (!TFuncs::deallocateAll())
|
||||
{
|
||||
auto itr = begin();
|
||||
auto endItr = end();
|
||||
while (itr != endItr)
|
||||
{
|
||||
auto entry = itr.mCurEntry;
|
||||
++itr;
|
||||
FreeIdx(entry);
|
||||
}
|
||||
TFuncs::deallocate(this->mHashHeads);
|
||||
TFuncs::deallocate(this->mEntries);
|
||||
}
|
||||
|
||||
this->mHashSize = cDefaultHashSize;
|
||||
this->mHashHeads = NULL;
|
||||
this->mEntries = NULL;
|
||||
this->mCount = 0;
|
||||
}
|
||||
|
||||
Iterator begin()
|
||||
{
|
||||
return ++Iterator(this);
|
||||
}
|
||||
|
||||
Iterator end()
|
||||
{
|
||||
Iterator itr(this);
|
||||
itr.mCurBucket = this->mHashSize;
|
||||
return itr;
|
||||
}
|
||||
};
|
||||
|
||||
NS_BF_END;
|
|
@ -30,7 +30,7 @@ struct MultiHashSetFuncs
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T, typename TFuncs = AllocatorCLib<T> >
|
||||
template <typename T, typename TFuncs = AllocatorCLib >
|
||||
class MultiHashSet : public TFuncs
|
||||
{
|
||||
public:
|
||||
|
@ -180,7 +180,7 @@ protected:
|
|||
void ResizeEntries(int newSize)
|
||||
{
|
||||
BF_ASSERT(newSize >= mAllocSize);
|
||||
Entry* newEntries = (Entry*)TFuncs::Allocate(sizeof(Entry) * newSize, alignof(Entry));
|
||||
Entry* newEntries = TFuncs::allocate<Entry>(newSize);
|
||||
|
||||
for (int i = 0; i < mCount; i++)
|
||||
{
|
||||
|
@ -195,7 +195,7 @@ protected:
|
|||
newEntries[i].mHashCode = -1;
|
||||
}
|
||||
|
||||
TFuncs::Deallocate(mEntries);
|
||||
TFuncs::deallocate(mEntries);
|
||||
|
||||
mEntries = newEntries;
|
||||
mAllocSize = (int)newSize;
|
||||
|
@ -276,7 +276,7 @@ public:
|
|||
{
|
||||
if (this->mHashHeads == NULL)
|
||||
{
|
||||
this->mHashHeads = (int*)TFuncs::Allocate(sizeof(int) * mHashSize, alignof(int));
|
||||
this->mHashHeads = TFuncs::allocate<int>(mHashSize);
|
||||
memset(this->mHashHeads, -1, sizeof(int) * mHashSize);
|
||||
}
|
||||
|
||||
|
@ -298,7 +298,7 @@ public:
|
|||
{
|
||||
if (this->mHashHeads == NULL)
|
||||
{
|
||||
this->mHashHeads = (int*)TFuncs::Allocate(sizeof(int) * mHashSize, alignof(int));
|
||||
this->mHashHeads = TFuncs::allocate<int>(mHashSize);
|
||||
memset(this->mHashHeads, -1, sizeof(int) * mHashSize);
|
||||
}
|
||||
|
||||
|
@ -332,7 +332,7 @@ public:
|
|||
|
||||
void Rehash(int newHashSize)
|
||||
{
|
||||
auto newHashHeads = (int*)TFuncs::Allocate(sizeof(int) * newHashSize, alignof(int));
|
||||
auto newHashHeads = TFuncs::allocate<int>(newHashSize);
|
||||
memset(newHashHeads, -1, sizeof(int) * newHashSize);
|
||||
|
||||
if (mHashHeads != NULL)
|
||||
|
@ -364,7 +364,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
TFuncs::Deallocate(mHashHeads);
|
||||
TFuncs::deallocate(mHashHeads);
|
||||
}
|
||||
mHashHeads = newHashHeads;
|
||||
mHashSize = newHashSize;
|
||||
|
@ -492,7 +492,7 @@ public:
|
|||
|
||||
void Clear()
|
||||
{
|
||||
if (!TFuncs::DeallocateAll())
|
||||
if (!TFuncs::deallocateAll())
|
||||
{
|
||||
auto itr = begin();
|
||||
auto endItr = end();
|
||||
|
@ -502,8 +502,8 @@ public:
|
|||
++itr;
|
||||
FreeIdx(entry);
|
||||
}
|
||||
TFuncs::Deallocate(this->mHashHeads);
|
||||
TFuncs::Deallocate(this->mEntries);
|
||||
TFuncs::deallocate(this->mHashHeads);
|
||||
TFuncs::deallocate(this->mEntries);
|
||||
}
|
||||
|
||||
this->mHashSize = cDefaultHashSize;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
NS_BF_BEGIN;
|
||||
|
||||
template <typename T, typename TAlloc = AllocatorCLib<T> >
|
||||
template <typename T, typename TAlloc = AllocatorCLib >
|
||||
class SizedArrayBase : protected TAlloc
|
||||
{
|
||||
public:
|
||||
|
@ -378,7 +378,7 @@ protected:
|
|||
|
||||
void Grow(intptr newSize)
|
||||
{
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (this->mSize > 0)
|
||||
|
@ -533,7 +533,7 @@ public:
|
|||
{
|
||||
intptr newSize = this->mAllocSize + this->mAllocSize / 2 + 1;
|
||||
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (idx > 0) // Copy left of idx
|
||||
|
@ -562,7 +562,7 @@ public:
|
|||
{
|
||||
intptr newSize = BF_MAX(this->mSize + size, this->mAllocSize + this->mAllocSize / 2 + 1);
|
||||
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (idx > 0) // Copy left of idx
|
||||
|
@ -638,7 +638,7 @@ public:
|
|||
protected:
|
||||
void Grow(intptr newSize)
|
||||
{
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (this->mSize > 0)
|
||||
|
@ -761,7 +761,7 @@ public:
|
|||
{
|
||||
intptr newSize = this->mAllocSize + this->mAllocSize / 2 + 1;
|
||||
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (idx > 0) // Copy left of idx
|
||||
|
@ -790,7 +790,7 @@ public:
|
|||
{
|
||||
intptr newSize = BF_MAX(this->mSize + size, this->mAllocSize + this->mAllocSize / 2 + 1);
|
||||
|
||||
T* newVals = TAlloc::allocate(newSize);
|
||||
T* newVals = TAlloc::allocate<T>(newSize);
|
||||
if (this->mVals != NULL)
|
||||
{
|
||||
if (idx > 0) // Copy left of idx
|
||||
|
@ -854,14 +854,14 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T, typename TAlloc = AllocatorCLib<T> >
|
||||
template <typename T, typename TAlloc = AllocatorCLib >
|
||||
class SizedArrayImpl : public SizedArrayBaseT<T, TAlloc, std::is_pod<T>::value>
|
||||
{
|
||||
public:
|
||||
typedef SizedArrayBaseT<T, TAlloc, std::is_pod<T>::value> _Base;
|
||||
};
|
||||
|
||||
template <typename T, int TInternalSize, typename TAlloc = AllocatorCLib<T> >
|
||||
template <typename T, int TInternalSize, typename TAlloc = AllocatorCLib >
|
||||
class SizedArray : public SizedArrayImpl<T, TAlloc>
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue