Add support for allocator type in Dictionary
This commit is contained in:
@@ -121,7 +121,7 @@ public:
|
||||
/// Gets the raw dictionary of assets (loaded or during load).
|
||||
/// </summary>
|
||||
/// <returns>The collection of assets.</returns>
|
||||
static const Dictionary<Guid, Asset*>& GetAssetsRaw();
|
||||
static const Dictionary<Guid, Asset*, HeapAllocation>& GetAssetsRaw();
|
||||
|
||||
/// <summary>
|
||||
/// Loads asset and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async.
|
||||
|
||||
@@ -129,7 +129,7 @@ public:
|
||||
/// Initializes a new instance of the <see cref="Array"/> class.
|
||||
/// </summary>
|
||||
/// <param name="other">The other collection to move.</param>
|
||||
FORCE_INLINE Array(Array&& other) noexcept
|
||||
Array(Array&& other) noexcept
|
||||
{
|
||||
_count = other._count;
|
||||
_capacity = other._capacity;
|
||||
@@ -896,9 +896,7 @@ public:
|
||||
struct Iterator
|
||||
{
|
||||
friend Array;
|
||||
|
||||
private:
|
||||
|
||||
Array* _array;
|
||||
int32 _index;
|
||||
|
||||
@@ -928,6 +926,12 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
Iterator(Iterator&& i)
|
||||
: _array(i._array)
|
||||
, _index(i._index)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
FORCE_INLINE Array* GetArray() const
|
||||
@@ -940,26 +944,16 @@ public:
|
||||
return _index;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Checks if iterator is in the end of the collection.
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsEnd() const
|
||||
{
|
||||
return _index == _array->Count();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if iterator is not in the end of the collection.
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsNotEnd() const
|
||||
{
|
||||
return _index != _array->Count();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
FORCE_INLINE T& operator*() const
|
||||
{
|
||||
return _array->Get()[_index];
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/Memory/Memory.h"
|
||||
#include "Engine/Core/Memory/Allocation.h"
|
||||
#include "Engine/Core/Collections/HashFunctions.h"
|
||||
#include "Engine/Core/Collections/Config.h"
|
||||
|
||||
/// <summary>
|
||||
/// Template for unordered dictionary with mapped key with value pairs.
|
||||
/// </summary>
|
||||
template<typename KeyType, typename ValueType>
|
||||
template<typename KeyType, typename ValueType, typename AllocationType = HeapAllocation>
|
||||
API_CLASS(InBuild) class Dictionary
|
||||
{
|
||||
friend Dictionary;
|
||||
@@ -29,7 +30,6 @@ public:
|
||||
Occupied = 2,
|
||||
};
|
||||
|
||||
public:
|
||||
/// <summary>The key.</summary>
|
||||
KeyType Key;
|
||||
/// <summary>The value.</summary>
|
||||
@@ -100,12 +100,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename AllocationType::template Data<Bucket> AllocationData;
|
||||
|
||||
private:
|
||||
|
||||
int32 _elementsCount = 0;
|
||||
int32 _deletedCount = 0;
|
||||
int32 _tableSize = 0;
|
||||
Bucket* _table = nullptr;
|
||||
int32 _size = 0;
|
||||
AllocationData _allocation;
|
||||
|
||||
public:
|
||||
|
||||
@@ -125,6 +127,24 @@ public:
|
||||
SetCapacity(capacity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Dictionary"/> class.
|
||||
/// </summary>
|
||||
/// <param name="other">The other collection to move.</param>
|
||||
Dictionary(Dictionary&& other) noexcept
|
||||
: _elementsCount(other._elementsCount)
|
||||
, _deletedCount(other._deletedCount)
|
||||
, _size(other._size)
|
||||
{
|
||||
_elementsCount = other._elementsCount;
|
||||
_deletedCount = other._deletedCount;
|
||||
_size = other._size;
|
||||
other._elementsCount = 0;
|
||||
other._deletedCount = 0;
|
||||
other._size = 0;
|
||||
_allocation.Swap(other._allocation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Dictionary"/> class.
|
||||
/// </summary>
|
||||
@@ -141,18 +161,39 @@ public:
|
||||
/// <returns>The reference to this.</returns>
|
||||
Dictionary& operator=(const Dictionary& other)
|
||||
{
|
||||
// Ensure we're not trying to set to itself
|
||||
if (this != &other)
|
||||
Clone(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the data from the other collection.
|
||||
/// </summary>
|
||||
/// <param name="other">The other collection to move.</param>
|
||||
/// <returns>The reference to this.</returns>
|
||||
Dictionary& operator=(Dictionary&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
Clear();
|
||||
_allocation.Free();
|
||||
_elementsCount = other._elementsCount;
|
||||
_deletedCount = other._deletedCount;
|
||||
_size = other._size;
|
||||
other._elementsCount = 0;
|
||||
other._deletedCount = 0;
|
||||
other._size = 0;
|
||||
_allocation.Swap(other._allocation);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="Dictionary"/> class.
|
||||
/// </summary>
|
||||
~Dictionary()
|
||||
{
|
||||
Cleanup();
|
||||
Clear();
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -170,7 +211,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE int32 Capacity() const
|
||||
{
|
||||
return _tableSize;
|
||||
return _size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -198,7 +239,6 @@ public:
|
||||
{
|
||||
friend Dictionary;
|
||||
private:
|
||||
|
||||
Dictionary& _collection;
|
||||
int32 _index;
|
||||
|
||||
@@ -222,39 +262,37 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
Iterator(Iterator&& i)
|
||||
: _collection(i._collection)
|
||||
, _index(i._index)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Checks if iterator is in the end of the collection.
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsEnd() const
|
||||
{
|
||||
return _index == _collection._tableSize;
|
||||
return _index == _collection._size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if iterator is not in the end of the collection.
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsNotEnd() const
|
||||
{
|
||||
return _index != _collection._tableSize;
|
||||
return _index != _collection._size;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
FORCE_INLINE Bucket& operator*() const
|
||||
{
|
||||
return _collection._table[_index];
|
||||
return _collection._allocation.Get()[_index];
|
||||
}
|
||||
|
||||
FORCE_INLINE Bucket* operator->() const
|
||||
{
|
||||
return &_collection._table[_index];
|
||||
return &_collection._allocation.Get()[_index];
|
||||
}
|
||||
|
||||
FORCE_INLINE explicit operator bool() const
|
||||
{
|
||||
return _index >= 0 && _index < _collection._tableSize;
|
||||
return _index >= 0 && _index < _collection._size;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool operator!() const
|
||||
@@ -272,17 +310,16 @@ public:
|
||||
return _index != v._index || &_collection != &v._collection;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Iterator& operator++()
|
||||
{
|
||||
const int32 capacity = _collection.Capacity();
|
||||
if (_index != capacity)
|
||||
{
|
||||
const Bucket* data = _collection._allocation.Get();
|
||||
do
|
||||
{
|
||||
_index++;
|
||||
} while (_index != capacity && _collection._table[_index].IsNotOccupied());
|
||||
} while (_index != capacity && data[_index].IsNotOccupied());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -298,10 +335,11 @@ public:
|
||||
{
|
||||
if (_index > 0)
|
||||
{
|
||||
const Bucket* data = _collection._allocation.Get();
|
||||
do
|
||||
{
|
||||
_index--;
|
||||
} while (_index > 0 && _collection._table[_index].IsNotOccupied());
|
||||
} while (_index > 0 && data[_index].IsNotOccupied());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -333,13 +371,11 @@ public:
|
||||
|
||||
// Check if that key has been already added
|
||||
if (pos.ObjectIndex != -1)
|
||||
{
|
||||
return _table[pos.ObjectIndex].Value;
|
||||
}
|
||||
return _allocation.Get()[pos.ObjectIndex].Value;
|
||||
|
||||
// Insert
|
||||
ASSERT(pos.FreeSlotIndex != -1);
|
||||
auto bucket = &_table[pos.FreeSlotIndex];
|
||||
auto bucket = &_allocation.Get()[pos.FreeSlotIndex];
|
||||
bucket->Occupy(key);
|
||||
_elementsCount++;
|
||||
return bucket->Value;
|
||||
@@ -355,9 +391,8 @@ public:
|
||||
{
|
||||
FindPositionResult pos;
|
||||
FindPosition(key, pos);
|
||||
|
||||
ASSERT(pos.ObjectIndex != -1);
|
||||
return _table[pos.ObjectIndex].Value;
|
||||
return _allocation.Get()[pos.ObjectIndex].Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -393,13 +428,11 @@ public:
|
||||
{
|
||||
if (IsEmpty())
|
||||
return false;
|
||||
|
||||
FindPositionResult pos;
|
||||
FindPosition(key, pos);
|
||||
|
||||
if (pos.ObjectIndex == -1)
|
||||
return false;
|
||||
result = _table[pos.ObjectIndex].Value;
|
||||
result = _allocation.Get()[pos.ObjectIndex].Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -413,13 +446,11 @@ public:
|
||||
{
|
||||
if (IsEmpty())
|
||||
return nullptr;
|
||||
|
||||
FindPositionResult pos;
|
||||
FindPosition(key, pos);
|
||||
|
||||
if (pos.ObjectIndex == -1)
|
||||
return nullptr;
|
||||
return &_table[pos.ObjectIndex].Value;
|
||||
return (ValueType*)&_allocation.Get()[pos.ObjectIndex].Value;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -429,24 +460,28 @@ public:
|
||||
/// </summary>
|
||||
void Clear()
|
||||
{
|
||||
if (_table)
|
||||
if (_elementsCount + _deletedCount != 0)
|
||||
{
|
||||
// Free all buckets
|
||||
for (int32 i = 0; i < _tableSize; i++)
|
||||
_table[i].Free();
|
||||
Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
data[i].Free();
|
||||
_elementsCount = _deletedCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the collection and delete value objects.
|
||||
/// Note: collection must contain pointers to the objects that have public destructor and be allocated using New method.
|
||||
/// </summary>
|
||||
#if defined(_MSC_VER)
|
||||
template<typename = typename TEnableIf<TIsPointer<ValueType>::Value>::Type>
|
||||
#endif
|
||||
void ClearDelete()
|
||||
{
|
||||
for (auto i = Begin(); i.IsNotEnd(); ++i)
|
||||
{
|
||||
if (i->Value)
|
||||
::Delete(i->Value);
|
||||
Delete(i->Value);
|
||||
}
|
||||
Clear();
|
||||
}
|
||||
@@ -458,74 +493,45 @@ public:
|
||||
/// <param name="preserveContents">Enables preserving collection contents during resizing.</param>
|
||||
void SetCapacity(int32 capacity, bool preserveContents = true)
|
||||
{
|
||||
// Check if capacity won't change
|
||||
if (capacity == Capacity())
|
||||
return;
|
||||
|
||||
// Cache previous state
|
||||
ASSERT(capacity >= 0);
|
||||
Bucket* oldTable = _table;
|
||||
const int32 oldTableSize = _tableSize;
|
||||
|
||||
// Clear elements counters
|
||||
AllocationData oldAllocation;
|
||||
oldAllocation.Swap(_allocation);
|
||||
const int32 oldSize = _size;
|
||||
const int32 oldElementsCount = _elementsCount;
|
||||
_deletedCount = _elementsCount = 0;
|
||||
|
||||
// Check if need to create a new table
|
||||
if (capacity > 0)
|
||||
if (capacity != 0 && (capacity & (capacity - 1)) != 0)
|
||||
{
|
||||
// Align capacity value to the next power of two (if it's not)
|
||||
if ((capacity & (capacity - 1)) != 0)
|
||||
capacity++;
|
||||
capacity |= capacity >> 1;
|
||||
capacity |= capacity >> 2;
|
||||
capacity |= capacity >> 4;
|
||||
capacity |= capacity >> 8;
|
||||
capacity |= capacity >> 16;
|
||||
capacity = capacity + 1;
|
||||
}
|
||||
_allocation.Allocate(capacity);
|
||||
Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < capacity; i++)
|
||||
data[i]._state = Bucket::Empty;
|
||||
_size = capacity;
|
||||
Bucket* oldData = oldAllocation.Get();
|
||||
if (oldElementsCount != 0 && preserveContents)
|
||||
{
|
||||
// TODO; move keys and values on realloc
|
||||
for (int32 i = 0; i < oldSize; i++)
|
||||
{
|
||||
capacity++;
|
||||
capacity |= capacity >> 1;
|
||||
capacity |= capacity >> 2;
|
||||
capacity |= capacity >> 4;
|
||||
capacity |= capacity >> 8;
|
||||
capacity |= capacity >> 16;
|
||||
capacity = capacity + 1;
|
||||
}
|
||||
|
||||
// Allocate new table
|
||||
_table = (Bucket*)Allocator::Allocate(capacity * sizeof(Bucket));
|
||||
_tableSize = capacity;
|
||||
for (int32 i = 0; i < capacity; i++)
|
||||
_table[i]._state = Bucket::Empty;
|
||||
if (oldElementsCount != 0 && preserveContents)
|
||||
{
|
||||
// Try to preserve all pairs in the collection
|
||||
for (int32 i = 0; i < oldTableSize; i++)
|
||||
{
|
||||
if (oldTable[i].IsOccupied())
|
||||
Add(oldTable[i].Key, oldTable[i].Value);
|
||||
}
|
||||
if (oldData[i].IsOccupied())
|
||||
Add(oldData[i].Key, oldData[i].Value);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (oldElementsCount != 0)
|
||||
{
|
||||
// Clear data
|
||||
_table = nullptr;
|
||||
_tableSize = 0;
|
||||
for (int32 i = 0; i < oldSize; i++)
|
||||
oldData[i].Free();
|
||||
}
|
||||
ASSERT(preserveContents == false || _elementsCount == oldElementsCount);
|
||||
|
||||
// Delete old table
|
||||
if (oldTable)
|
||||
{
|
||||
for (int32 i = 0; i < oldTableSize; i++)
|
||||
oldTable[i].Free();
|
||||
Allocator::Free(oldTable);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increases collection capacity by given extra size (content will be preserved).
|
||||
/// </summary>
|
||||
/// <param name="extraSize">The extra size to enlarge collection.</param>
|
||||
FORCE_INLINE void IncreaseCapacity(int32 extraSize)
|
||||
{
|
||||
ASSERT(extraSize >= 0);
|
||||
SetCapacity(Capacity() + extraSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -534,12 +540,11 @@ public:
|
||||
/// <param name="minCapacity">The minimum required capacity.</param>
|
||||
void EnsureCapacity(int32 minCapacity)
|
||||
{
|
||||
if (Capacity() >= minCapacity)
|
||||
if (_size >= minCapacity)
|
||||
return;
|
||||
|
||||
int32 capacity = Capacity() == 0 ? DICTIONARY_DEFAULT_CAPACITY : Capacity() * 2;
|
||||
if (capacity < minCapacity)
|
||||
capacity = minCapacity;
|
||||
if (minCapacity < DICTIONARY_DEFAULT_CAPACITY)
|
||||
minCapacity = DICTIONARY_DEFAULT_CAPACITY;
|
||||
const int32 capacity = _allocation.CalculateCapacityGrow(_size, minCapacity);
|
||||
SetCapacity(capacity);
|
||||
}
|
||||
|
||||
@@ -574,7 +579,7 @@ public:
|
||||
|
||||
// Insert
|
||||
ASSERT(pos.FreeSlotIndex != -1);
|
||||
Bucket* bucket = &_table[pos.FreeSlotIndex];
|
||||
Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex];
|
||||
bucket->Occupy(key, value);
|
||||
_elementsCount++;
|
||||
|
||||
@@ -602,7 +607,7 @@ public:
|
||||
|
||||
// Insert
|
||||
ASSERT(pos.FreeSlotIndex != -1);
|
||||
Bucket* bucket = &_table[pos.FreeSlotIndex];
|
||||
Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex];
|
||||
bucket->Occupy(key, MoveTemp(value));
|
||||
_elementsCount++;
|
||||
|
||||
@@ -636,7 +641,7 @@ public:
|
||||
|
||||
if (pos.ObjectIndex != -1)
|
||||
{
|
||||
_table[pos.ObjectIndex].Delete();
|
||||
_allocation.Get()[pos.ObjectIndex].Delete();
|
||||
_elementsCount--;
|
||||
_deletedCount++;
|
||||
return true;
|
||||
@@ -654,8 +659,8 @@ public:
|
||||
ASSERT(&i._collection == this);
|
||||
if (i)
|
||||
{
|
||||
ASSERT(_table[i._index].IsOccupied());
|
||||
_table[i._index].Delete();
|
||||
ASSERT(_allocation.Get()[i._index].IsOccupied());
|
||||
_allocation.Get()[i._index].Delete();
|
||||
_elementsCount--;
|
||||
_deletedCount++;
|
||||
return true;
|
||||
@@ -694,9 +699,10 @@ public:
|
||||
{
|
||||
if (HasItems())
|
||||
{
|
||||
for (int32 i = 0; i < _tableSize; i++)
|
||||
const Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
{
|
||||
if (_table[i].IsOccupied() && _table[i].Key == key)
|
||||
if (data[i].IsOccupied() && data[i].Key == key)
|
||||
return Iterator(*this, i);
|
||||
}
|
||||
}
|
||||
@@ -713,7 +719,6 @@ public:
|
||||
{
|
||||
if (IsEmpty())
|
||||
return false;
|
||||
|
||||
FindPositionResult pos;
|
||||
FindPosition(key, pos);
|
||||
return pos.ObjectIndex != -1;
|
||||
@@ -728,9 +733,10 @@ public:
|
||||
{
|
||||
if (HasItems())
|
||||
{
|
||||
for (int32 i = 0; i < _tableSize; i++)
|
||||
const Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
{
|
||||
if (_table[i].IsOccupied() && _table[i].Value == value)
|
||||
if (data[i].IsOccupied() && data[i].Value == value)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -747,17 +753,17 @@ public:
|
||||
{
|
||||
if (HasItems())
|
||||
{
|
||||
for (int32 i = 0; i < _tableSize; i++)
|
||||
const Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
{
|
||||
if (_table[i].IsOccupied() && _table[i].Value == value)
|
||||
if (data[i].IsOccupied() && data[i].Value == value)
|
||||
{
|
||||
if (key)
|
||||
*key = _table[i].Key;
|
||||
*key = data[i].Key;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -781,8 +787,8 @@ public:
|
||||
/// Gets the keys collection to the output array (will contain unique items).
|
||||
/// </summary>
|
||||
/// <param name="result">The result.</param>
|
||||
template<typename AllocationType>
|
||||
void GetKeys(Array<KeyType, AllocationType>& result) const
|
||||
template<typename ArrayAllocation>
|
||||
void GetKeys(Array<KeyType, ArrayAllocation>& result) const
|
||||
{
|
||||
for (auto i = Begin(); i.IsNotEnd(); ++i)
|
||||
result.Add(i->Key);
|
||||
@@ -792,8 +798,8 @@ public:
|
||||
/// Gets the values collection to the output array (may contain duplicates).
|
||||
/// </summary>
|
||||
/// <param name="result">The result.</param>
|
||||
template<typename AllocationType>
|
||||
void GetValues(Array<ValueType, AllocationType>& result) const
|
||||
template<typename ArrayAllocation>
|
||||
void GetValues(Array<ValueType, ArrayAllocation>& result) const
|
||||
{
|
||||
for (auto i = Begin(); i.IsNotEnd(); ++i)
|
||||
result.Add(i->Value);
|
||||
@@ -801,10 +807,6 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets iterator for beginning of the collection.
|
||||
/// </summary>
|
||||
/// <returns>Iterator for beginning of the collection.</returns>
|
||||
Iterator Begin() const
|
||||
{
|
||||
Iterator i(*this, -1);
|
||||
@@ -812,13 +814,9 @@ public:
|
||||
return i;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets iterator for ending of the collection.
|
||||
/// </summary>
|
||||
/// <returns>Iterator for ending of the collection.</returns>
|
||||
Iterator End() const
|
||||
{
|
||||
return Iterator(*this, _tableSize);
|
||||
return Iterator(*this, _size);
|
||||
}
|
||||
|
||||
Iterator begin()
|
||||
@@ -830,7 +828,7 @@ public:
|
||||
|
||||
FORCE_INLINE Iterator end()
|
||||
{
|
||||
return Iterator(*this, _tableSize);
|
||||
return Iterator(*this, _size);
|
||||
}
|
||||
|
||||
const Iterator begin() const
|
||||
@@ -842,7 +840,7 @@ public:
|
||||
|
||||
FORCE_INLINE const Iterator end() const
|
||||
{
|
||||
return Iterator(*this, _tableSize);
|
||||
return Iterator(*this, _size);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -868,17 +866,18 @@ protected:
|
||||
template<typename KeyComparableType>
|
||||
void FindPosition(const KeyComparableType& key, FindPositionResult& result) const
|
||||
{
|
||||
ASSERT(_table);
|
||||
const int32 tableSizeMinusOne = _tableSize - 1;
|
||||
ASSERT(_size);
|
||||
const int32 tableSizeMinusOne = _size - 1;
|
||||
int32 bucketIndex = GetHash(key) & tableSizeMinusOne;
|
||||
int32 insertPos = -1;
|
||||
int32 checksCount = 0;
|
||||
const Bucket* data = _allocation.Get();
|
||||
result.FreeSlotIndex = -1;
|
||||
|
||||
while (checksCount < _tableSize)
|
||||
while (checksCount < _size)
|
||||
{
|
||||
// Empty bucket
|
||||
if (_table[bucketIndex].IsEmpty())
|
||||
auto& bucket = data[bucketIndex];
|
||||
if (bucket.IsEmpty())
|
||||
{
|
||||
// Found place to insert
|
||||
result.ObjectIndex = -1;
|
||||
@@ -886,24 +885,22 @@ protected:
|
||||
return;
|
||||
}
|
||||
// Deleted bucket
|
||||
if (_table[bucketIndex].IsDeleted())
|
||||
if (bucket.IsDeleted())
|
||||
{
|
||||
// Keep searching but mark to insert
|
||||
if (insertPos == -1)
|
||||
insertPos = bucketIndex;
|
||||
}
|
||||
// Occupied bucket by target key
|
||||
else if (_table[bucketIndex].Key == key)
|
||||
else if (bucket.Key == key)
|
||||
{
|
||||
// Found key
|
||||
result.ObjectIndex = bucketIndex;
|
||||
return;
|
||||
}
|
||||
|
||||
checksCount++;
|
||||
bucketIndex = (bucketIndex + DICTIONARY_PROB_FUNC(_tableSize, checksCount)) & tableSizeMinusOne;
|
||||
bucketIndex = (bucketIndex + DICTIONARY_PROB_FUNC(_size, checksCount)) & tableSizeMinusOne;
|
||||
}
|
||||
|
||||
result.ObjectIndex = -1;
|
||||
result.FreeSlotIndex = insertPos;
|
||||
}
|
||||
|
||||
@@ -423,8 +423,6 @@ public:
|
||||
{
|
||||
if (Capacity() >= minCapacity)
|
||||
return;
|
||||
|
||||
// TODO: improve this, better collection growing and shrinking on remove
|
||||
int32 num = Capacity() == 0 ? DICTIONARY_DEFAULT_CAPACITY : Capacity() * 2;
|
||||
SetCapacity(Math::Clamp<int32>(num, minCapacity, MAX_int32 - 1410));
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ template<typename T, typename AllocationType>
|
||||
class Array;
|
||||
template<typename T, typename U>
|
||||
class Pair;
|
||||
template<typename KeyType, typename ValueType>
|
||||
template<typename KeyType, typename ValueType, typename AllocationType>
|
||||
class Dictionary;
|
||||
template<typename>
|
||||
class Function;
|
||||
|
||||
@@ -157,7 +157,7 @@ API_STRUCT(InBuild) struct FLAXENGINE_API Variant
|
||||
int32 Length;
|
||||
} AsBlob;
|
||||
|
||||
Dictionary<Variant, Variant>* AsDictionary;
|
||||
Dictionary<Variant, Variant, HeapAllocation>* AsDictionary;
|
||||
|
||||
byte AsData[16];
|
||||
};
|
||||
@@ -222,7 +222,7 @@ public:
|
||||
explicit Variant(const Matrix& v);
|
||||
Variant(Array<Variant, HeapAllocation>&& v);
|
||||
Variant(const Array<Variant, HeapAllocation>& v);
|
||||
explicit Variant(const Dictionary<Variant, Variant>& v);
|
||||
explicit Variant(const Dictionary<Variant, Variant, HeapAllocation>& v);
|
||||
explicit Variant(const CommonValue& v);
|
||||
|
||||
~Variant();
|
||||
|
||||
@@ -174,7 +174,7 @@ private:
|
||||
};
|
||||
|
||||
typedef Array<struct BatchedDrawCall, InlinedAllocation<8>> DrawCallsList;
|
||||
typedef Dictionary<DrawKey, struct BatchedDrawCall> BatchedDrawCalls;
|
||||
typedef Dictionary<DrawKey, struct BatchedDrawCall, HeapAllocation> BatchedDrawCalls;
|
||||
void DrawInstance(RenderContext& renderContext, FoliageInstance& instance, FoliageType& type, Model* model, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
|
||||
void DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, FoliageType& type, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
|
||||
#else
|
||||
|
||||
@@ -868,7 +868,7 @@ public:
|
||||
/// <param name="data">The input data.</param>
|
||||
/// <param name="idsMapping">The serialized objects Ids mapping. Can be used to convert the spawned objects ids and references to them.</param>
|
||||
/// <returns>The output actors.</returns>
|
||||
API_FUNCTION() static Array<Actor*> FromBytes(const Span<byte>& data, const Dictionary<Guid, Guid>& idsMapping);
|
||||
API_FUNCTION() static Array<Actor*> FromBytes(const Span<byte>& data, const Dictionary<Guid, Guid, HeapAllocation>& idsMapping);
|
||||
|
||||
/// <summary>
|
||||
/// Tries the get serialized objects ids from the raw bytes.
|
||||
|
||||
@@ -83,7 +83,7 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(PrefabManager);
|
||||
/// <param name="objectsCache">The options output objects cache that can be filled with prefab object id mapping to deserialized object (actor or script).</param>
|
||||
/// <param name="withSynchronization">True if perform prefab changes synchronization for the spawned objects. It will check if need to add new objects due to nested prefab modifications.</param>
|
||||
/// <returns>The created actor (root) or null if failed.</returns>
|
||||
static Actor* SpawnPrefab(Prefab* prefab, Actor* parent, Dictionary<Guid, const void*>* objectsCache, bool withSynchronization = false);
|
||||
static Actor* SpawnPrefab(Prefab* prefab, Actor* parent, Dictionary<Guid, const void*, HeapAllocation>* objectsCache, bool withSynchronization = false);
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
@@ -118,7 +118,7 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(PrefabManager);
|
||||
/// <summary>
|
||||
/// The prefabs references mapping table. Maps the prefab asset id to the collection of the root actors of the prefab instances.
|
||||
/// </summary>
|
||||
static Dictionary<Guid, Array<Actor*, HeapAllocation>> PrefabsReferences;
|
||||
static Dictionary<Guid, Array<Actor*, HeapAllocation>, HeapAllocation> PrefabsReferences;
|
||||
|
||||
/// <summary>
|
||||
/// Locks PrefabsReferences to be used in a multi threaded environment.
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
/// <summary>
|
||||
/// The actors collection lookup type (id -> actor).
|
||||
/// </summary>
|
||||
typedef Dictionary<Guid, Actor*> ActorsLookup;
|
||||
typedef Dictionary<Guid, Actor*, HeapAllocation> ActorsLookup;
|
||||
|
||||
#define DECLARE_SCENE_OBJECT(type) \
|
||||
DECLARE_SCRIPTING_TYPE(type)
|
||||
|
||||
@@ -11,7 +11,7 @@ class SceneObjectsFactory
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Dictionary<Actor*, const rapidjson_flax::Value*> ActorToRemovedObjectsDataLookup;
|
||||
typedef Dictionary<Actor*, const rapidjson_flax::Value*, HeapAllocation> ActorToRemovedObjectsDataLookup;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -705,7 +705,7 @@ public:
|
||||
/// Gets the process environment variables (pairs of key and value).
|
||||
/// </summary>
|
||||
/// <param name="result">The result.</param>
|
||||
static void GetEnvironmentVariables(Dictionary<String, String>& result);
|
||||
static void GetEnvironmentVariables(Dictionary<String, String, HeapAllocation>& result);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the environment variable value.
|
||||
@@ -753,7 +753,7 @@ public:
|
||||
/// <param name="environment">The process environment variables. If null the current process environment is used.</param>
|
||||
/// <param name="hiddenWindow">True if start process with hidden window.</param>
|
||||
/// <returns>Retrieves the termination status of the specified process. Valid only if processed ended.</returns>
|
||||
API_FUNCTION() static int32 RunProcess(const StringView& cmdLine, const StringView& workingDir, const Dictionary<String, String>& environment, bool hiddenWindow = true);
|
||||
API_FUNCTION() static int32 RunProcess(const StringView& cmdLine, const StringView& workingDir, const Dictionary<String, String, HeapAllocation>& environment, bool hiddenWindow = true);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the window.
|
||||
|
||||
@@ -75,12 +75,12 @@ public:
|
||||
static Rectangle GetMonitorBounds(const Vector2& screenPos);
|
||||
static Vector2 GetDesktopSize();
|
||||
static Rectangle GetVirtualDesktopBounds();
|
||||
static void GetEnvironmentVariables(Dictionary<String, String>& result);
|
||||
static void GetEnvironmentVariables(Dictionary<String, String, HeapAllocation>& result);
|
||||
static bool GetEnvironmentVariable(const String& name, String& value);
|
||||
static bool SetEnvironmentVariable(const String& name, const String& value);
|
||||
static int32 StartProcess(const StringView& filename, const StringView& args, const StringView& workingDir, bool hiddenWindow = false, bool waitForEnd = false);
|
||||
static int32 RunProcess(const StringView& cmdLine, const StringView& workingDir, bool hiddenWindow = true);
|
||||
static int32 RunProcess(const StringView& cmdLine, const StringView& workingDir, const Dictionary<String, String>& environment, bool hiddenWindow = true);
|
||||
static int32 RunProcess(const StringView& cmdLine, const StringView& workingDir, const Dictionary<String, String, HeapAllocation>& environment, bool hiddenWindow = true);
|
||||
static Window* CreateWindow(const CreateWindowSettings& settings);
|
||||
static void* LoadLibrary(const Char* filename);
|
||||
static Array<StackFrame, HeapAllocation> GetStackFrames(int32 skipCount = 0, int32 maxDepth = 60, void* context = nullptr);
|
||||
|
||||
@@ -293,7 +293,7 @@ public:
|
||||
/// <summary>
|
||||
/// The scripting types cache that maps the managed class to the scripting type index. Build after assembly is loaded and scripting types get the managed classes information.
|
||||
/// </summary>
|
||||
Dictionary<MonoClass*, int32> ClassToTypeIndex;
|
||||
Dictionary<MonoClass*, int32, HeapAllocation> ClassToTypeIndex;
|
||||
|
||||
static ScriptingObject* ManagedObjectSpawn(const ScriptingObjectSpawnParams& params);
|
||||
static MMethod* FindMethod(MClass* mclass, const ScriptingTypeMethodSignature& signature);
|
||||
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
typedef Dictionary<Guid, Guid> IdsMappingTable;
|
||||
typedef Dictionary<Guid, Guid, HeapAllocation> IdsMappingTable;
|
||||
|
||||
/// <summary>
|
||||
/// The objects lookup identifier mapping used to override the object ids on FindObject call (used by the object references deserialization).
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
target.AddMember(itr->name, itr->value, allocator);
|
||||
}
|
||||
|
||||
static void ChangeIds(Document& doc, const Dictionary<Guid, Guid>& mapping);
|
||||
static void ChangeIds(Document& doc, const Dictionary<Guid, Guid, HeapAllocation>& mapping);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -41,19 +41,19 @@
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<!-- Dictionary<Key, Value> -->
|
||||
<Type Name="Dictionary<*,*>">
|
||||
<DisplayString>{{ Size={_elementsCount} Capacity={_tableSize} }}</DisplayString>
|
||||
<!-- Dictionary<Key, Value, HeapAllocation> -->
|
||||
<Type Name="Dictionary<*,*,*>">
|
||||
<DisplayString>{{ Size={_elementsCount} Capacity={_size} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[Size]" ExcludeView="simple">_elementsCount</Item>
|
||||
<Item Name="[Capacity]" ExcludeView="simple">_tableSize</Item>
|
||||
<Item Name="[Capacity]" ExcludeView="simple">_size</Item>
|
||||
<CustomListItems MaxItemsPerView="5000" ExcludeView="Test">
|
||||
<Variable Name="i" InitialValue="0" />
|
||||
<Size>_elementsCount</Size>
|
||||
<Loop>
|
||||
<Break Condition="i == _tableSize" />
|
||||
<If Condition="_table[i]._state == 2">
|
||||
<Item>_table[i]</Item>
|
||||
<Break Condition="i == _size" />
|
||||
<If Condition="_allocation._data[i]._state == 2">
|
||||
<Item>_allocation._data[i]</Item>
|
||||
</If>
|
||||
<Exec>i++</Exec>
|
||||
</Loop>
|
||||
|
||||
Reference in New Issue
Block a user