rework pipeline builder systems list to use linked list

This commit is contained in:
Mikhail 2024-09-02 17:29:19 +08:00
parent 7ae651080b
commit ecb3cd5d11

View File

@ -207,9 +207,12 @@ namespace DCFApixels.DragonECS
{ {
public class Builder : IEcsModule public class Builder : IEcsModule
{ {
private SystemRecord[] _systemRecords = new SystemRecord[256]; private SystemNode[] _systemNodes = new SystemNode[256];
private int _systemRecordsCount = 0; private int _startIndex = -1;
private int _systemRecordsInrement = 0; private int _endIndex = -1;
private int _systemNodesCount = 0;
private int _freeIndex = -1;
private int _freeNodesCount = 0;
private readonly Dictionary<string, LayerSystemsList> _layerLists = new Dictionary<string, LayerSystemsList>(8); private readonly Dictionary<string, LayerSystemsList> _layerLists = new Dictionary<string, LayerSystemsList>(8);
private readonly List<InitDeclaredRunner> _initDeclaredRunners = new List<InitDeclaredRunner>(4); private readonly List<InitDeclaredRunner> _initDeclaredRunners = new List<InitDeclaredRunner>(4);
@ -221,9 +224,9 @@ namespace DCFApixels.DragonECS
private AddParams _defaultAddParams = new AddParams(BASIC_LAYER, 0, false); private AddParams _defaultAddParams = new AddParams(BASIC_LAYER, 0, false);
#region Properties #region Properties
private ReadOnlySpan<SystemRecord> SystemRecords private ReadOnlySpan<SystemNode> SystemRecords
{ {
get { return new ReadOnlySpan<SystemRecord>(_systemRecords, 0, _systemRecordsCount); } get { return new ReadOnlySpan<SystemNode>(_systemNodes, 0, _systemNodesCount); }
} }
#endregion #endregion
@ -274,23 +277,48 @@ namespace DCFApixels.DragonECS
} }
} }
AddRecord_Internal(system, prms.layerName, prms.sortOrder, prms.isUnique, _systemRecordsInrement++); AddNode_Internal(system, prms.layerName, prms.sortOrder, prms.isUnique);
return this; return this;
} }
private void AddRecord_Internal(IEcsProcess system, string layer, int sortOrder, bool isUnique, int addOrder) private void AddNode_Internal(IEcsProcess system, string layer, int sortOrder, bool isUnique)
{ {
SystemRecord record = new SystemRecord(system, layer, addOrder, sortOrder, isUnique); SystemNode record = new SystemNode(system, layer, sortOrder, isUnique);
int newIndex;
if (_freeNodesCount <= 0)
{
if (_systemNodes.Length <= _systemNodesCount)
{
Array.Resize(ref _systemNodes, _systemNodesCount << 1);
}
newIndex = _systemNodesCount;
_systemNodes[newIndex] = record;
}
else
{
_freeNodesCount--;
newIndex = _freeIndex;
_freeIndex = _systemNodes[_freeIndex].next;
}
_systemNodesCount++;
if (_systemNodesCount == 1)
{
_startIndex = newIndex;
}
else
{
_systemNodes[_endIndex].next = newIndex;
}
_systemNodes[newIndex] = record;
_endIndex = newIndex;
if (_layerLists.TryGetValue(layer, out LayerSystemsList list) == false) if (_layerLists.TryGetValue(layer, out LayerSystemsList list) == false)
{ {
list = new LayerSystemsList(layer); list = new LayerSystemsList(layer);
_layerLists.Add(layer, list); _layerLists.Add(layer, list);
} }
list.lasyInitSystemsCount++; list.lasyInitSystemsCount++;
if (_systemRecords.Length <= _systemRecordsCount)
{
Array.Resize(ref _systemRecords, _systemRecordsCount << 1);
}
_systemRecords[_systemRecordsCount++] = record;
} }
#endregion #endregion
@ -355,30 +383,54 @@ namespace DCFApixels.DragonECS
} }
Layers.MergeWith(other.Layers); Layers.MergeWith(other.Layers);
//_systemRecordsInrement + otherRecord.addOrder смещает порядок так что новые системы встают в конец очереди, но сохраняют порядок addOrder
foreach (var otherRecord in other.SystemRecords) foreach (var otherRecord in other.SystemRecords)
{ {
AddRecord_Internal(otherRecord.system, otherRecord.layerName, otherRecord.sortOrder, otherRecord.isUnique, _systemRecordsInrement + otherRecord.addOrder); AddNode_Internal(otherRecord.system, otherRecord.layerName, otherRecord.sortOrder, otherRecord.isUnique);
} }
_systemRecordsInrement += other._systemRecordsInrement;
} }
#endregion #endregion
#region Remove #region Remove
private void RemoveAt(int index) private void RemoveAt(int prevIndex, int removedNodeIndex)
{ {
ref var slot = ref _systemRecords[index]; ref var removedeNode = ref _systemNodes[removedNodeIndex];
_layerLists[slot.layerName].lasyInitSystemsCount--; _layerLists[removedeNode.layerName].lasyInitSystemsCount--;
slot = _systemRecords[--_systemRecordsCount]; _systemNodes[prevIndex].next = removedeNode.next;
removedeNode = default;
if (_endIndex == removedNodeIndex)
{
_endIndex = prevIndex;
}
if (_freeNodesCount > 0)
{
removedeNode.next = _freeIndex;
}
_freeIndex = removedNodeIndex;
_freeNodesCount++;
_systemNodesCount--;
} }
public Builder Remove<TSystem>() public Builder Remove<TSystem>()
{ {
for (int i = 0; i < _systemRecordsCount; i++) if (_systemNodesCount <= 1)
{ {
if (_systemRecords[i].system is TSystem) if (_systemNodesCount == 1 && _systemNodes[0].system is TSystem)
{ {
RemoveAt(i--); _systemNodesCount = 0;
} }
return this;
}
int enumIndex = _startIndex;
for (int i = 1; i < _systemNodesCount; i++)
{
int nextIndex = _systemNodes[enumIndex].next;
if (_systemNodes[nextIndex].system is TSystem)
{
RemoveAt(enumIndex, nextIndex);
nextIndex = _systemNodes[enumIndex].next;
}
enumIndex = nextIndex;
} }
return this; return this;
} }
@ -419,18 +471,20 @@ namespace DCFApixels.DragonECS
allSystemsLength += basicLayerList.lasyInitSystemsCount + 1; allSystemsLength += basicLayerList.lasyInitSystemsCount + 1;
basicLayerList.Init(); basicLayerList.Init();
for (int i = 0, iMax = _systemRecordsCount; i < iMax; i++) int enumIndex = _startIndex;
for (int i = 0, iMax = _systemNodesCount; i < iMax; i++)
{ {
ref var record = ref _systemRecords[i]; ref var node = ref _systemNodes[enumIndex];
var list = _layerLists[record.layerName]; var list = _layerLists[node.layerName];
if (list.IsInit == false) if (list.IsInit == false)
{ {
list = basicLayerList; list = basicLayerList;
} }
if (record.isUnique == false || uniqueSystemsSet.Add(record.system.GetType())) if (node.isUnique == false || uniqueSystemsSet.Add(node.system.GetType()))
{ {
list.Add(record.system, record.addOrder, record.sortOrder, record.isUnique); list.Add(node.system, node.sortOrder, node.isUnique);
} }
enumIndex = node.next;
} }
@ -713,7 +767,7 @@ namespace DCFApixels.DragonECS
if (IsInit) { Throw.UndefinedException(); } if (IsInit) { Throw.UndefinedException(); }
records = new Item[lasyInitSystemsCount + 1]; records = new Item[lasyInitSystemsCount + 1];
Add(new SystemsLayerMarkerSystem(_layerName), int.MinValue, int.MinValue, false); Add(new SystemsLayerMarkerSystem(_layerName), int.MinValue, false);
} }
public void AddList(LayerSystemsList other) public void AddList(LayerSystemsList other)
{ {
@ -723,9 +777,9 @@ namespace DCFApixels.DragonECS
AddItem_Internal(otherRecord); AddItem_Internal(otherRecord);
} }
} }
public void Add(IEcsProcess system, int addOrder, int sortOrder, bool isUnique) public void Add(IEcsProcess system, int sortOrder, bool isUnique)
{ {
AddItem_Internal(new Item(system, addOrder, sortOrder, isUnique)); AddItem_Internal(new Item(system, sortOrder, isUnique));
} }
private void AddItem_Internal(Item item) private void AddItem_Internal(Item item)
{ {
@ -734,16 +788,14 @@ namespace DCFApixels.DragonECS
if (recordsCount <= 1) if (recordsCount <= 1)
{ {
_lastSortOrder = item.sortOrder; _lastSortOrder = item.sortOrder;
_lastAddOrder = item.addOrder;
} }
else if (_lastSortOrder > item.sortOrder || _lastAddOrder > item.addOrder) else if (_lastSortOrder > item.sortOrder)
{ {
_isSorted = false; _isSorted = false;
} }
else else
{ {
_lastSortOrder = item.sortOrder; _lastSortOrder = item.sortOrder;
_lastAddOrder = item.addOrder;
} }
} }
@ -771,26 +823,22 @@ namespace DCFApixels.DragonECS
Array.Sort(records, 1, recordsCount - 1); Array.Sort(records, 1, recordsCount - 1);
_isSorted = true; _isSorted = true;
_lastSortOrder = records[recordsCount - 1].sortOrder; _lastSortOrder = records[recordsCount - 1].sortOrder;
_lastAddOrder = records[recordsCount - 1].addOrder;
} }
} }
private readonly struct Item : IComparable<Item> private readonly struct Item : IComparable<Item>
{ {
public readonly IEcsProcess system; public readonly IEcsProcess system;
public readonly int addOrder;
public readonly int sortOrder; public readonly int sortOrder;
public readonly bool isUnique; public readonly bool isUnique;
public Item(IEcsProcess system, int addOrder, int sortOrder, bool isUnique) public Item(IEcsProcess system, int sortOrder, bool isUnique)
{ {
this.system = system; this.system = system;
this.addOrder = addOrder;
this.sortOrder = sortOrder; this.sortOrder = sortOrder;
this.isUnique = isUnique; this.isUnique = isUnique;
} }
public int CompareTo(Item other) public int CompareTo(Item other)
{ {
int c = sortOrder - other.sortOrder; return sortOrder - other.sortOrder;
return c == 0 ? addOrder - other.addOrder : c;
} }
} }
#endregion #endregion
@ -798,7 +846,7 @@ namespace DCFApixels.DragonECS
#region SerializableTemplate #region SerializableTemplate
public EcsPipelineTemplate GenerateSerializableTemplate() public EcsPipelineTemplate GenerateSerializableTemplate()
{ {
Array.Sort(_systemRecords, 0, _systemRecordsCount); Array.Sort(_systemNodes, 0, _systemNodesCount);
var records = SystemRecords; var records = SystemRecords;
EcsPipelineTemplate result = new EcsPipelineTemplate(); EcsPipelineTemplate result = new EcsPipelineTemplate();
result.layers = new string[Layers.Count]; result.layers = new string[Layers.Count];
@ -815,25 +863,20 @@ namespace DCFApixels.DragonECS
#region SystemRecord #region SystemRecord
[StructLayout(LayoutKind.Auto)] [StructLayout(LayoutKind.Auto)]
private readonly struct SystemRecord : IComparable<SystemRecord> private struct SystemNode
{ {
public readonly IEcsProcess system; public readonly IEcsProcess system;
public readonly string layerName; public readonly string layerName;
public readonly int addOrder;
public readonly int sortOrder; public readonly int sortOrder;
public readonly bool isUnique; public readonly bool isUnique;
public SystemRecord(IEcsProcess system, string layerName, int addOrder, int sortOrder, bool isUnique) public int next;
public SystemNode(IEcsProcess system, string layerName, int sortOrder, bool isUnique, int next = -1)
{ {
this.system = system; this.system = system;
this.layerName = layerName; this.layerName = layerName;
this.addOrder = addOrder;
this.sortOrder = sortOrder; this.sortOrder = sortOrder;
this.isUnique = isUnique; this.isUnique = isUnique;
} this.next = next;
public int CompareTo(SystemRecord other)
{
int c = sortOrder - other.sortOrder;
return c == 0 ? addOrder - other.addOrder : c;
} }
} }
#endregion #endregion