Theater-ECS/src/Internal/Containers/PagedSparseSet.bf

87 lines
No EOL
2.1 KiB
Beef

namespace Theater_ECS.Internal.Containers;
using System;
using System.Collections;
class PagedSparseSet
{
public const uint32 PageSize = 4096;
private List<List<Entity>> _sparse = new .()~ DeleteContainerAndItems!(_);
private List<Entity> _packed = new .() ~ delete _;
private UList _packedEntities ~ delete _;
private function void(void* data) _deallocationFunction = null;
public this(int_cosize size)
{
_packedEntities = new .(size);
}
public bool Contains(Entity e)
{
return _sparse[e.Index/PageSize][e.Index % PageSize] != Entity.Null;
}
public void Add(Entity e, void* toAdd)
{
EnsureLoadedPage(e.Index/PageSize);
_packed.Add(e);
_packedEntities.Add(toAdd);
_sparse[e.Index/PageSize][e.Index % PageSize] = (.)_packed.Count-1;
}
public bool Remove(Entity e, bool cleanup = false)
{
EnsurePage(e.Index/PageSize);
if(_sparse[e.Index/PageSize] == null)
return false;
if(_deallocationFunction != null && !cleanup)
_deallocationFunction(_packedEntities[(.)(_sparse[e.Index/PageSize][e.Index % PageSize].Index)]);
let toRm = _packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index];
let b = _packed.Back;
_packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index] = b;
_packed.Back = toRm;
_sparse[b.Index/PageSize][b.Index % PageSize] = Entity(e.Index, b.Version);
_sparse[e.Index/PageSize][e.Index % PageSize] = Entity.Null;
_packed.PopBack();
return true;
}
[Inline, Unchecked]
public void* Get(Entity e)
{
return _packedEntities[(.)(_sparse[e.Index/PageSize][e.Index % PageSize].Index)];
}
public Span<Entity> GetAll()
{
return _packed;
}
public int_cosize Count() => (.)_packed.Count;
///Ensure that a page exist and is loaded
public void EnsureLoadedPage(uint32 page)
{
EnsurePage(page);
if(_sparse[page] == null)
{
_sparse[page] = new List<Entity>(PageSize);
_sparse[page].[Friend]Count = 4096;
_sparse[page].SetAll(Entity.Null);
}
}
///Ensure that a page exists, it might be null though
private void EnsurePage(uint32 page)
{
while(_sparse.Count < page+1)
_sparse.Add(null);
}
}