Skip to content

Instantly share code, notes, and snippets.

@Hexlord
Created January 10, 2021 11:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hexlord/2c7b9b4bff27be13e2a4b9f73e036756 to your computer and use it in GitHub Desktop.
Save Hexlord/2c7b9b4bff27be13e2a4b9f73e036756 to your computer and use it in GitHub Desktop.
Collection for creation of elements with persistent handle identification through unordered set
#pragma once
#include <Array/Array.h>
namespace SE {
struct FHandle {
uint32 UnorderedIndex;
uint32 Generation;
};
template<typename T, typename TAllocator>
class TCollection {
};
template<typename T, bool SingleFrame>
class TCollection<T, THeapAllocator<SingleFrame>> {
public:
FHandle Create() {
Check(Ordered.GetSize() == Unordered.GetSize());
if(Elements.GetSize() < Ordered.GetSize()) {
const uint32 OrderedIndex = Elements.GetSize();
Elements.Create();
return Ordered[OrderedIndex];
}
Check(Elements.GetSize() == Ordered.GetSize());
const uint32 NewIndex = Elements.GetSize();
FHandle NewHandle = FHandle{NewIndex, 0};
Ordered.Add(NewHandle);
Unordered.Add(NewIndex);
Elements.Create();
return NewHandle;
}
bool Contains(FHandle Handle) {
if(Handle.UnorderedIndex < Unordered.GetSize()) {
return Ordered[Unordered[Handle.UnorderedIndex]].Generation == Handle.Generation;
}
return false;
}
void RemoveSwap(FHandle Handle) {
Check(Contains(Handle));
const uint32 LastIndex = Ordered.GetSize() - 1;
const uint32 OrderedIndex = Unordered[Handle.UnorderedIndex];
if(OrderedIndex != LastIndex) {
const uint32 UnorderedIndex = Ordered[LastIndex].UnorderedIndex;
const uint32 Generation = Ordered[LastIndex].Generation;
Check(Handle.UnorderedIndex != UnorderedIndex);
Ordered[LastIndex].UnorderedIndex = Ordered[OrderedIndex].UnorderedIndex;
Ordered[LastIndex].Generation = Ordered[OrderedIndex].Generation + 1;
Ordered[OrderedIndex].UnorderedIndex = UnorderedIndex;
Ordered[OrderedIndex].Generation = Generation;
Unordered[Handle.UnorderedIndex] = Unordered[UnorderedIndex];
Unordered[UnorderedIndex] = OrderedIndex;
} else {
Ordered[OrderedIndex].Generation ++;
}
Elements.RemoveSwap(OrderedIndex);
}
const T &operator[](FHandle Handle) const {
Check(Contains(Handle));
return Elements[Unordered[Handle.UnorderedIndex]];
}
T &operator[](FHandle Handle) {
Check(Contains(Handle));
return Elements[Unordered[Handle.UnorderedIndex]];
}
[[nodiscard]] uint32 GetSize() const {
return Elements.GetSize();
}
[[nodiscard]] T *operator*() {
return *Elements;
}
[[nodiscard]] const T *operator*() const {
return *Elements;
}
private:
TArray<uint32, THeapAllocator<SingleFrame>> Unordered;
TArray<FHandle, THeapAllocator<SingleFrame>> Ordered;
TArray<T, THeapAllocator<SingleFrame>> Elements;
};
template<typename T>
using TFrameCollection = TCollection<T, TFrameAllocator>;
template<typename T>
using TPersistentCollection = TCollection<T, TPersistentAllocator>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment