From dca48b335a87da5afb2e03ed0297013610329428 Mon Sep 17 00:00:00 2001 From: Mateusz Karbowiak <69864511+mtszkarbowiak@users.noreply.github.com> Date: Thu, 31 Oct 2024 02:41:51 +0100 Subject: [PATCH] Hash collections bucket state enum extracted This is a small compilation time optimization by reducing total number of generated types. Should not change runtime behavior. --- Source/Engine/Core/Collections/BucketState.h | 15 +++++++ Source/Engine/Core/Collections/Dictionary.h | 44 +++++++++----------- Source/Engine/Core/Collections/HashSet.h | 42 ++++++++----------- 3 files changed, 52 insertions(+), 49 deletions(-) create mode 100644 Source/Engine/Core/Collections/BucketState.h diff --git a/Source/Engine/Core/Collections/BucketState.h b/Source/Engine/Core/Collections/BucketState.h new file mode 100644 index 000000000..16cbdb845 --- /dev/null +++ b/Source/Engine/Core/Collections/BucketState.h @@ -0,0 +1,15 @@ +// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. + +#pragma once + +#include "Engine/Core/Types/BaseTypes.h" + +/// +/// Tells if the object is occupied, and if not, if the bucket is a subject of compaction. +/// +enum class BucketState : byte +{ + Empty = 0, + Deleted = 1, + Occupied = 2, +}; diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index 794cfc455..efb7bafcf 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -4,6 +4,7 @@ #include "Engine/Core/Memory/Memory.h" #include "Engine/Core/Memory/Allocation.h" +#include "Engine/Core/Collections/BucketState.h" #include "Engine/Core/Collections/HashFunctions.h" #include "Engine/Core/Collections/Config.h" @@ -25,34 +26,27 @@ public: { friend Dictionary; - enum State : byte - { - Empty = 0, - Deleted = 1, - Occupied = 2, - }; - /// The key. KeyType Key; /// The value. ValueType Value; private: - State _state; + BucketState _state; FORCE_INLINE void Free() { - if (_state == Occupied) + if (_state == BucketState::Occupied) { Memory::DestructItem(&Key); Memory::DestructItem(&Value); } - _state = Empty; + _state = BucketState::Empty; } FORCE_INLINE void Delete() { - _state = Deleted; + _state = BucketState::Deleted; Memory::DestructItem(&Key); Memory::DestructItem(&Value); } @@ -62,7 +56,7 @@ public: { Memory::ConstructItems(&Key, &key, 1); Memory::ConstructItem(&Value); - _state = Occupied; + _state = BucketState::Occupied; } template @@ -70,7 +64,7 @@ public: { Memory::ConstructItems(&Key, &key, 1); Memory::ConstructItems(&Value, &value, 1); - _state = Occupied; + _state = BucketState::Occupied; } template @@ -78,27 +72,27 @@ public: { Memory::ConstructItems(&Key, &key, 1); Memory::MoveItems(&Value, &value, 1); - _state = Occupied; + _state = BucketState::Occupied; } FORCE_INLINE bool IsEmpty() const { - return _state == Empty; + return _state == BucketState::Empty; } FORCE_INLINE bool IsDeleted() const { - return _state == Deleted; + return _state == BucketState::Deleted; } FORCE_INLINE bool IsOccupied() const { - return _state == Occupied; + return _state == BucketState::Occupied; } FORCE_INLINE bool IsNotOccupied() const { - return _state != Occupied; + return _state != BucketState::Occupied; } }; @@ -127,10 +121,10 @@ private: Bucket& toBucket = toData[i]; Memory::MoveItems(&toBucket.Key, &fromBucket.Key, 1); Memory::MoveItems(&toBucket.Value, &fromBucket.Value, 1); - toBucket._state = Bucket::Occupied; + toBucket._state = BucketState::Occupied; Memory::DestructItem(&fromBucket.Key); Memory::DestructItem(&fromBucket.Value); - fromBucket._state = Bucket::Empty; + fromBucket._state = BucketState::Empty; } } from.Free(); @@ -566,7 +560,7 @@ public: _allocation.Allocate(capacity); Bucket* data = _allocation.Get(); for (int32 i = 0; i < capacity; i++) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; } _size = capacity; Bucket* oldData = oldAllocation.Get(); @@ -583,7 +577,7 @@ public: Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex]; Memory::MoveItems(&bucket->Key, &oldBucket.Key, 1); Memory::MoveItems(&bucket->Value, &oldBucket.Value, 1); - bucket->_state = Bucket::Occupied; + bucket->_state = BucketState::Occupied; ++_elementsCount; } } @@ -967,7 +961,7 @@ private: // Fast path if it's empty Bucket* data = _allocation.Get(); for (int32 i = 0; i < _size; i++) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; } else { @@ -977,7 +971,7 @@ private: _allocation.Allocate(_size); Bucket* data = _allocation.Get(); for (int32 i = 0; i < _size; i++) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; Bucket* oldData = oldAllocation.Get(); FindPositionResult pos; for (int32 i = 0; i < _size; i++) @@ -990,7 +984,7 @@ private: Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex]; Memory::MoveItems(&bucket->Key, &oldBucket.Key, 1); Memory::MoveItems(&bucket->Value, &oldBucket.Value, 1); - bucket->_state = Bucket::Occupied; + bucket->_state = BucketState::Occupied; } } for (int32 i = 0; i < _size; i++) diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h index 2e90dae4b..aa61354fd 100644 --- a/Source/Engine/Core/Collections/HashSet.h +++ b/Source/Engine/Core/Collections/HashSet.h @@ -4,6 +4,7 @@ #include "Engine/Core/Memory/Memory.h" #include "Engine/Core/Memory/Allocation.h" +#include "Engine/Core/Collections/BucketState.h" #include "Engine/Core/Collections/HashFunctions.h" #include "Engine/Core/Collections/Config.h" @@ -24,29 +25,22 @@ public: { friend HashSet; - enum State : byte - { - Empty, - Deleted, - Occupied, - }; - /// The item. T Item; private: - State _state; + BucketState _state; FORCE_INLINE void Free() { - if (_state == Occupied) + if (_state == BucketState::Occupied) Memory::DestructItem(&Item); - _state = Empty; + _state = BucketState::Empty; } FORCE_INLINE void Delete() { - _state = Deleted; + _state = BucketState::Deleted; Memory::DestructItem(&Item); } @@ -54,34 +48,34 @@ public: FORCE_INLINE void Occupy(const ItemType& item) { Memory::ConstructItems(&Item, &item, 1); - _state = Occupied; + _state = BucketState::Occupied; } template FORCE_INLINE void Occupy(ItemType&& item) { Memory::MoveItems(&Item, &item, 1); - _state = Occupied; + _state = BucketState::Occupied; } FORCE_INLINE bool IsEmpty() const { - return _state == Empty; + return _state == BucketState::Empty; } FORCE_INLINE bool IsDeleted() const { - return _state == Deleted; + return _state == BucketState::Deleted; } FORCE_INLINE bool IsOccupied() const { - return _state == Occupied; + return _state == BucketState::Occupied; } FORCE_INLINE bool IsNotOccupied() const { - return _state != Occupied; + return _state != BucketState::Occupied; } }; @@ -109,9 +103,9 @@ private: { Bucket& toBucket = toData[i]; Memory::MoveItems(&toBucket.Item, &fromBucket.Item, 1); - toBucket._state = Bucket::Occupied; + toBucket._state = BucketState::Occupied; Memory::DestructItem(&fromBucket.Item); - fromBucket._state = Bucket::Empty; + fromBucket._state = BucketState::Empty; } } from.Free(); @@ -443,7 +437,7 @@ public: _allocation.Allocate(capacity); Bucket* data = _allocation.Get(); for (int32 i = 0; i < capacity; i++) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; } _size = capacity; Bucket* oldData = oldAllocation.Get(); @@ -459,7 +453,7 @@ public: ASSERT(pos.FreeSlotIndex != -1); Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex]; Memory::MoveItems(&bucket->Item, &oldBucket.Item, 1); - bucket->_state = Bucket::Occupied; + bucket->_state = BucketState::Occupied; _elementsCount++; } } @@ -763,7 +757,7 @@ private: // Fast path if it's empty Bucket* data = _allocation.Get(); for (int32 i = 0; i < _size; ++i) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; } else { @@ -773,7 +767,7 @@ private: _allocation.Allocate(_size); Bucket* data = _allocation.Get(); for (int32 i = 0; i < _size; ++i) - data[i]._state = Bucket::Empty; + data[i]._state = BucketState::Empty; Bucket* oldData = oldAllocation.Get(); FindPositionResult pos; for (int32 i = 0; i < _size; ++i) @@ -785,7 +779,7 @@ private: ASSERT(pos.FreeSlotIndex != -1); Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex]; Memory::MoveItems(&bucket->Item, &oldBucket.Item, 1); - bucket->_state = Bucket::Occupied; + bucket->_state = BucketState::Occupied; } } for (int32 i = 0; i < _size; ++i)