stash/ not work

This commit is contained in:
Mikhail 2024-02-05 18:32:20 +08:00
parent 653a798af7
commit 5ee2f6a0a6
5 changed files with 466 additions and 178 deletions

View File

@ -169,9 +169,10 @@ namespace DCFApixels.DragonECS
} }
public void Del(int relEntityID) public void Del(int relEntityID)
{ {
var (startEntityID, _) = _source.GetRelationInfo(relEntityID); var (startEntityID, endEntityID) = _source.GetRelationInfo(relEntityID);
ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID]; ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID];
_startBaskets.RemoveFromBasket(startEntityID, relInfo.startNodeIndex); _startBaskets.RemoveNextNodeFromBasket(startEntityID, relInfo.startNodeIndex);
_endBaskets.RemoveNextNodeFromBasket(endEntityID, relInfo.endNodeIndex);
} }
public void DelStart(int startEntityID) public void DelStart(int startEntityID)
{ {
@ -179,7 +180,7 @@ namespace DCFApixels.DragonECS
{ {
var endEntityID = _source.GetRelEnd(relEntityID); var endEntityID = _source.GetRelEnd(relEntityID);
ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID]; ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID];
_endBaskets.RemoveFromBasket(endEntityID, relInfo.startNodeIndex); _endBaskets.RemoveNextNodeFromBasket(endEntityID, relInfo.startNodeIndex);
} }
_startBaskets.RemoveBasket(startEntityID); _startBaskets.RemoveBasket(startEntityID);
} }
@ -189,7 +190,7 @@ namespace DCFApixels.DragonECS
{ {
var startEntityID = _source.GetRelStart(relEntityID); var startEntityID = _source.GetRelStart(relEntityID);
ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID]; ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID];
_startBaskets.RemoveFromBasket(startEntityID, relInfo.endNodeIndex); _startBaskets.RemoveNextNodeFromBasket(startEntityID, relInfo.endNodeIndex);
} }
_endBaskets.RemoveBasket(endEntityID); _endBaskets.RemoveBasket(endEntityID);
} }
@ -198,7 +199,6 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DelStartAndDelRelEntities(int startEntityID, EcsArc arc) private void DelStartAndDelRelEntities(int startEntityID, EcsArc arc)
{ {
foreach (var relEntityID in _startBaskets.GetBasketIterator(startEntityID)) foreach (var relEntityID in _startBaskets.GetBasketIterator(startEntityID))
{ {
arc.ArcWorld.TryDelEntity(relEntityID); arc.ArcWorld.TryDelEntity(relEntityID);
@ -214,25 +214,29 @@ namespace DCFApixels.DragonECS
} }
public struct FriendEcsArc public struct FriendEcsArc
{ {
private EcsGraph _join; public readonly EcsGraph join;
public FriendEcsArc(EcsArc arc, EcsGraph join) public FriendEcsArc(EcsArc arc, EcsGraph join)
{ {
if (arc.IsInit_Internal != false) if (arc.IsInit_Internal != false)
{ {
Throw.UndefinedException(); Throw.UndefinedException();
} }
_join = join; if(join == null)
{
Throw.ArgumentNull();
}
this.join = join;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void DelStartAndDelRelEntities(int startEntityID, EcsArc arc) public void DelStartAndDelRelEntities(int startEntityID, EcsArc arc)
{ {
_join.DelStartAndDelRelEntities(startEntityID, arc); join.DelStartAndDelRelEntities(startEntityID, arc);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void DelEndAndDelRelEntities(int endEntityID, EcsArc arc) public void DelEndAndDelRelEntities(int endEntityID, EcsArc arc)
{ {
_join.DelEndAndDelRelEntities(endEntityID, arc); join.DelEndAndDelRelEntities(endEntityID, arc);
} }
} }
#endregion #endregion
@ -244,11 +248,11 @@ namespace DCFApixels.DragonECS
} }
public bool HasStart(int startEntityID) public bool HasStart(int startEntityID)
{ {
return _startBaskets.GetBasketNodesCount(startEntityID) > 0; return _startBaskets.HasBasket(startEntityID);
} }
public bool HasEnd(int endEntityID) public bool HasEnd(int endEntityID)
{ {
return _endBaskets.GetBasketNodesCount(endEntityID) > 0; return _endBaskets.HasBasket(endEntityID);
} }
#endregion #endregion

View File

@ -104,17 +104,31 @@ namespace DCFApixels.DragonECS.Relations.Internal
} }
internal static unsafe class UnmanagedArrayUtility internal static unsafe class UnmanagedArrayUtility
{ {
public static readonly int PtrSize = sizeof(IntPtr);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T** NewPointersArray<T>(int capacity) where T : unmanaged
{
return (T**)Marshal.AllocHGlobal(capacity * PtrSize).ToPointer();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T* New<T>(int capacity) where T : unmanaged public static T* New<T>(int capacity) where T : unmanaged
{ {
return (T*)Marshal.AllocHGlobal(Marshal.SizeOf<T>() * capacity).ToPointer(); return (T*)Marshal.AllocHGlobal(Marshal.SizeOf<T>() * capacity).ToPointer();
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void New<T>(out T* ptr, int capacity) where T : unmanaged public static T** NewAndInitPointersArray<T>(int capacity) where T : unmanaged
{ {
ptr = (T*)Marshal.AllocHGlobal(Marshal.SizeOf<T>(default) * capacity).ToPointer(); int newSize = PtrSize * capacity;
T** newPointer = (T**)Marshal.AllocHGlobal(newSize).ToPointer();
for (int i = 0; i < newSize; i++)
{
*(newPointer + i) = null;
} }
return newPointer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T* NewAndInit<T>(int capacity) where T : unmanaged public static T* NewAndInit<T>(int capacity) where T : unmanaged
{ {
@ -122,21 +136,13 @@ namespace DCFApixels.DragonECS.Relations.Internal
byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer(); byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
for (int i = 0; i < newSize; i++) for (int i = 0; i < newSize; i++)
{
*(newPointer + i) = 0; *(newPointer + i) = 0;
}
return (T*)newPointer; return (T*)newPointer;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void NewAndInit<T>(out T* ptr, int capacity) where T : unmanaged
{
int newSize = Marshal.SizeOf(typeof(T)) * capacity;
byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
for (int i = 0; i < newSize; i++)
*(newPointer + i) = 0;
ptr = (T*)newPointer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Free(void* pointer) public static void Free(void* pointer)
@ -144,6 +150,13 @@ namespace DCFApixels.DragonECS.Relations.Internal
Marshal.FreeHGlobal(new IntPtr(pointer)); Marshal.FreeHGlobal(new IntPtr(pointer));
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void FreePointersArray<T>(ref T** pointer, ref int length) where T : unmanaged
{
Marshal.FreeHGlobal(new IntPtr(pointer));
pointer = null;
length = 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Free<T>(ref T* pointer, ref int length) where T : unmanaged public static void Free<T>(ref T* pointer, ref int length) where T : unmanaged
{ {
Marshal.FreeHGlobal(new IntPtr(pointer)); Marshal.FreeHGlobal(new IntPtr(pointer));
@ -151,6 +164,16 @@ namespace DCFApixels.DragonECS.Relations.Internal
length = 0; length = 0;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T** ClonePointersArray<T>(T** sourcePtr, int length) where T : unmanaged
{
T** clone = NewPointersArray<T>(length);
for (int i = 0; i < length; i++)
{
clone[i] = sourcePtr[i];
}
return clone;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T* Clone<T>(T* sourcePtr, int length) where T : unmanaged public static T* Clone<T>(T* sourcePtr, int length) where T : unmanaged
{ {
@ -162,6 +185,13 @@ namespace DCFApixels.DragonECS.Relations.Internal
return clone; return clone;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T** ResizePointersArray<T>(T** oldPointer, int newCount) where T : unmanaged
{
return (T**)Marshal.ReAllocHGlobal(
new IntPtr(oldPointer),
new IntPtr(PtrSize * newCount)).ToPointer();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T* Resize<T>(void* oldPointer, int newCount) where T : unmanaged public static T* Resize<T>(void* oldPointer, int newCount) where T : unmanaged
{ {
@ -170,6 +200,30 @@ namespace DCFApixels.DragonECS.Relations.Internal
new IntPtr(Marshal.SizeOf<T>(default) * newCount)).ToPointer(); new IntPtr(Marshal.SizeOf<T>(default) * newCount)).ToPointer();
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T** ResizeAndInitPointersArray<T>(T** oldPointer, int oldSize, int newSize) where T : unmanaged
{
int newByteSize = PtrSize * newSize;
T** result = (T**)Marshal.ReAllocHGlobal((IntPtr)(oldPointer), newByteSize);
for (int i = oldSize; i < newSize; i++)
{
result[i] = null;
}
return result;
}
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
//public static void* ResizeAndInitPointersArray(void* oldPointer, int oldSize, int newSize)
//{
// int newByteSize = PtrSize * newSize;
// void** result = (void**)Marshal.ReAllocHGlobal((IntPtr)(oldPointer), newByteSize);
//
// for (int i = oldSize; i < newSize; i++)
// {
// result[i] = null;
// }
// return result;
//}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T* ResizeAndInit<T>(void* oldPointer, int oldSize, int newSize) where T : unmanaged public static T* ResizeAndInit<T>(void* oldPointer, int oldSize, int newSize) where T : unmanaged
{ {
int sizeT = Marshal.SizeOf<T>(default); int sizeT = Marshal.SizeOf<T>(default);
@ -180,6 +234,8 @@ namespace DCFApixels.DragonECS.Relations.Internal
return result; return result;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Init(byte* pointer, int startByteIndex, int endByteIndex) private static void Init(byte* pointer, int startByteIndex, int endByteIndex)
{ {

View File

@ -1,21 +1,22 @@
using System; using DCFApixels.DragonECS.Relations.Internal;
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
[DebuggerTypeProxy(typeof(DebuggerProxy))] [DebuggerTypeProxy(typeof(DebuggerProxy))]
internal class BasketList internal unsafe class BasketList
{ {
public const int RECYCLE = -1; public const int NULL = 0;
public const int HEAD = 0;
private BasketInfo[] _baskets = new BasketInfo[64]; private UnsafePointersArray<BasketNode> _basketNodePointers;
private Node[] _nodes; private UnsafeArray<Node> _nodes;
private int _recycledListLast = -1; private int _recycledListHead = NULL;
#region Constructors #region Constructors
public BasketList() : this(16) { } public BasketList() : this(16) { }
@ -32,18 +33,28 @@ namespace DCFApixels.DragonECS
{ {
_nodes[i].next = 0; _nodes[i].next = 0;
} }
for (int i = 0; i < _baskets.Length; i++) for (int i = 0; i < _basketNodePointers.Length; i++)
{ {
_baskets[i] = default; _basketNodePointers[i] = BasketNode.EmptyInstancePtr;
} }
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private void Resize(int newSize) private void ResizeNodes(int newSize)
{ {
int oldSize = _nodes.Length; int oldSize = _nodes.Length;
Array.Resize(ref _nodes, newSize); IntPtr offset = (IntPtr)_nodes.ptr;
int leftNode = newSize - 1; UnsafeArray.Resize(ref _nodes, newSize);
offset = ((IntPtr)_nodes.ptr - offset) / 8;
for (int i = 0; i < _basketNodePointers.Length; i++)
{
if (_basketNodePointers[i] != BasketNode.EmptyInstancePtr)
{
_basketNodePointers.ptr[i] += offset;
}
}
int leftNode = NULL;
for (int i = oldSize; i < newSize; i++) for (int i = oldSize; i < newSize; i++)
{ {
Link(i, leftNode); Link(i, leftNode);
@ -54,8 +65,13 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private void Initialize(int newSize) private void Initialize(int newSize)
{ {
_nodes = new Node[newSize]; _basketNodePointers = new UnsafePointersArray<BasketNode>(64);
int leftNode = newSize - 1; for (int i = 0; i < 64; i++)
{
_basketNodePointers[i] = BasketNode.EmptyInstancePtr;
}
_nodes = new UnsafeArray<Node>(newSize, true);
int leftNode = NULL;
for (int i = 1; i < newSize; i++) for (int i = 1; i < newSize; i++)
{ {
Link(i, leftNode); Link(i, leftNode);
@ -64,10 +80,14 @@ namespace DCFApixels.DragonECS
LinkToRecycled(newSize - 1, 1); LinkToRecycled(newSize - 1, 1);
} }
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
//public int GetBasketNodesCount(int basketIndex)
//{
//}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetBasketNodesCount(int basketIndex) public bool HasBasket(int basketIndex)
{ {
return _baskets[basketIndex].count; return _basketNodePointers[basketIndex] != BasketNode.EmptyInstancePtr;
} }
@ -89,188 +109,210 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveFromBasket(int basketIndex, int nodeIndex) public void RemoveNextNodeFromBasket(int basketIndex, int prevNodeIndex) // +
{ {
#if DEBUG #if DEBUG
if (nodeIndex <= 0) if (prevNodeIndex <= 0)
{ {
//Throw.ArgumentOutOfRange(); //Throw.ArgumentOutOfRange();
return; return;
} }
#endif #endif
ref BasketInfo basketInfo = ref _baskets[basketIndex]; ref BasketNode* basketNode = ref _basketNodePointers[basketIndex];
if (basketNode == BasketNode.EmptyInstancePtr)
ref var node = ref _nodes[nodeIndex];
int nextNode = node.next;
Link(node.prev, nextNode);
LinkToRecycled(nodeIndex, nodeIndex);
if (basketInfo.nodeIndex == nodeIndex)
{ {
basketInfo.nodeIndex = nextNode; //Поидее тут не должно быть пусто
Throw.UndefinedException();
}
int targetNodeIndex = _nodes[prevNodeIndex].next;
int nextNodeIndex = _nodes[targetNodeIndex].next;
if(targetNodeIndex == 15)
{
}
Link(prevNodeIndex, nextNodeIndex);
LinkToRecycled(targetNodeIndex);
if (basketNode->nodeIndex == targetNodeIndex)
{
basketNode->nodeIndex = nextNodeIndex;
}
if (--basketNode->count <= 0)
{
LinkToRecycled(prevNodeIndex);
basketNode = BasketNode.EmptyInstancePtr;
} }
basketInfo.count--;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int AddToBasket(int basketIndex, int value) private void CreateBasket(ref BasketNode* toPointer) // +
{ {
ref BasketInfo basketInfo = ref _baskets[basketIndex]; toPointer = (BasketNode*)TakeRecycledNodePtr();
*toPointer = BasketNode.Empty;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int AddToBasket(int basketIndex, int value) // +
{
ref BasketNode* basketNode = ref _basketNodePointers[basketIndex];
int prevNodeIndex;
int newNodeIndex = TakeRecycledNode(); int newNodeIndex = TakeRecycledNode();
if (basketInfo.count == 0) if (basketNode == BasketNode.EmptyInstancePtr)
{ {
//_nodes[newNodeIndex].Set(value, 0, 0); CreateBasket(ref basketNode);
prevNodeIndex = (int)((Node*)basketNode - _nodes.ptr);
_nodes[newNodeIndex].value = value; _nodes[newNodeIndex].value = value;
} }
else else
{ {
// int nextNodeIndex = basketInfo.nodeIndex; _nodes[newNodeIndex].Set(value, basketNode->nodeIndex);
// //_nodes[newNodeIndex].Set(value, 0, nextNodeIndex); prevNodeIndex = basketNode->nodeIndex;
// _nodes[newNodeIndex].Set_Value_Next(value, nextNodeIndex);
// //_nodes[nextNodeIndex].prev = newNodeIndex;
_nodes[newNodeIndex].Set_Value_Next(value, basketInfo.nodeIndex);
} }
basketInfo.nodeIndex = newNodeIndex; basketNode->nodeIndex = newNodeIndex;
basketInfo.count++; basketNode->count++;
return newNodeIndex; return prevNodeIndex;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private int TakeRecycledNode() private Node* TakeRecycledNodePtr() // +
{ {
if (_recycledListLast == -1) if (_recycledListHead == NULL)
{ {
Resize(_nodes.Length << 1); ResizeNodes(_nodes.Length << 1);
} }
int resultNode = _recycledListLast; Node* resultNode = _nodes.ptr + _recycledListHead;
_recycledListLast = _nodes[resultNode].prev; _recycledListHead = resultNode->next;
resultNode->next = 0;
return resultNode; return resultNode;
} }
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
//private void Separate(int leftNodeIndex, int rightNodeIndex)
//{
// _nodes[rightNodeIndex].prev = 0;
// _nodes[leftNodeIndex].next = 0;
//}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Link(int leftNodeIndex, int rightNodeIndex) private int TakeRecycledNode() // +
{
if (_recycledListHead == NULL)
{
ResizeNodes(_nodes.Length << 1);
}
int resultNode = _recycledListHead;
_recycledListHead = _nodes[resultNode].next;
_nodes[resultNode].next = 0;
return resultNode;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Link(int leftNodeIndex, int rightNodeIndex) // +
{ {
_nodes[rightNodeIndex].prev = leftNodeIndex;
_nodes[leftNodeIndex].next = rightNodeIndex; _nodes[leftNodeIndex].next = rightNodeIndex;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void LinkToRecycled(int startNodeIndex, int endNodeIndex) private void LinkToRecycled(int nodeIndex) // +
{ {
if (_recycledListLast <= -1) if(nodeIndex == 15)
{ {
_nodes[startNodeIndex].prev = RECYCLE;
}
if (_recycledListHead >= 0)
{
_nodes[nodeIndex].next = _recycledListHead;
} }
else else
{ {
Link(_recycledListLast, startNodeIndex); _nodes[nodeIndex].next = 0;
} }
_recycledListLast = endNodeIndex; _recycledListHead = nodeIndex;
int i = 0;
int cureNodeIndex = _recycledListHead;
while (cureNodeIndex != NULL)
{
int nextNodeIndex = _nodes[cureNodeIndex].next;
if (i > _nodes.Length)
{
Console.WriteLine("WTF");
}
cureNodeIndex = nextNodeIndex;
i++;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void LinkToRecycled(int startNodeIndex, int endNodeIndex) // +
{
if (_recycledListHead >= 0)
{
_nodes[endNodeIndex].next = _recycledListHead;
}
_recycledListHead = startNodeIndex;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveBasket(int basketIndex) public void RemoveBasket(int basketIndex) // +
{ {
ref BasketInfo basket = ref _baskets[basketIndex]; ref BasketNode* basketNode = ref _basketNodePointers[basketIndex];
if (basketNode == null) { Throw.UndefinedException(); }
int startNodeIndex = basket.nodeIndex; int startBasketNodeIndex = (int)(basketNode - (BasketNode*)_nodes.ptr);
int endNodeIndex = startNodeIndex;
ref Node startNode = ref _nodes[startNodeIndex]; int endNodeIndex = startBasketNodeIndex;
for (int i = 0, n = basket.count; i < n; i++) for (int i = 0, n = basketNode->count; i < n; i++)
{ {
endNodeIndex = _nodes[endNodeIndex].next; endNodeIndex = _nodes[endNodeIndex].next;
} }
ref Node endNode = ref _nodes[endNodeIndex]; LinkToRecycled(startBasketNodeIndex, endNodeIndex);
basketNode = BasketNode.EmptyInstancePtr;
LinkToRecycled(startNodeIndex, endNodeIndex);
Link(startNode.prev, endNode.next);
basket.count = 0;
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
public void UpBasketsSize(int minSize) public void UpBasketsSize(int minSize)
{ {
if (minSize > _baskets.Length) if (minSize > _basketNodePointers.Length)
{ {
int newSize = 1 << (GetHighBitNumber((uint)minSize - 1) + 1); int newSize = ArrayUtility.NormalizeSizeToPowerOfTwo(minSize);
Array.Resize(ref _baskets, newSize); int oldSize = _basketNodePointers.Length;
} UnsafePointersArray.Resize(ref _basketNodePointers, newSize);
} for (int i = oldSize; i < newSize; i++)
private static int GetHighBitNumber(uint bits)
{ {
if (bits == 0) _basketNodePointers[i] = BasketNode.EmptyInstancePtr;
{
return -1;
} }
int bit = 0;
if ((bits & 0xFFFF0000) != 0)
{
bits >>= 16;
bit |= 16;
} }
if ((bits & 0xFF00) != 0)
{
bits >>= 8;
bit |= 8;
}
if ((bits & 0xF0) != 0)
{
bits >>= 4;
bit |= 4;
}
if ((bits & 0xC) != 0)
{
bits >>= 2;
bit |= 2;
}
if ((bits & 0x2) != 0)
{
bit |= 1;
}
return bit;
} }
#region Node #region Node
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)] [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
public struct Node public struct Node
{ {
public static readonly Node Empty = new Node() { value = 0, next = -1 }; public static readonly Node Empty = new Node() { value = 0, next = NULL };
public int value; public int value;
/// <summary>next node index</summary> /// <summary>next node index</summary>
public int next; public int next;
/// <summary>prev node index</summary>
public int prev;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Set(int value, int prev, int next) public void Set(int value, int next)
{
this.value = value;
this.next = next;
this.prev = prev;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Set_Value_Next(int value, int next)
{ {
this.value = value; this.value = value;
this.next = next; this.next = next;
} }
public override string ToString() => $"node({prev}<>{next} v:{value})"; public override string ToString() => $"node(>{next} v:{value})";
} }
#endregion #endregion
#region BasketInfo #region BasketInfo
private struct BasketInfo [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
private struct BasketNode
{ {
public static readonly BasketInfo Empty = new BasketInfo() { nodeIndex = 0, count = 0, }; public static readonly BasketNode Empty = new BasketNode() { nodeIndex = 0, count = 0, };
public int nodeIndex; public static BasketNode* EmptyInstancePtr;
static BasketNode()
{
void* ptr = (void*)Marshal.AllocHGlobal(Marshal.SizeOf<BasketNode>(default));
EmptyInstancePtr = (BasketNode*)ptr;
*EmptyInstancePtr = default;
}
public int count; public int count;
public int nodeIndex;
public override string ToString() => $"basket_info(i:{nodeIndex} c:{count})"; public override string ToString() => $"basket_info(i:{nodeIndex} c:{count})";
private static BasketNode* EmptyInstancePtr_Debug => EmptyInstancePtr;
} }
#endregion #endregion
@ -291,7 +333,7 @@ namespace DCFApixels.DragonECS
private readonly int _basketIndex; private readonly int _basketIndex;
public int Count public int Count
{ {
get { return _basketList._baskets[_basketIndex].count; } get { return _basketList._basketNodePointers[_basketIndex]->count; }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -307,18 +349,19 @@ namespace DCFApixels.DragonECS
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public struct Enumerator : IEnumerator<int> public struct Enumerator : IEnumerator<int>
{ {
private readonly Node[] _nodes; private readonly UnsafeArray<Node> _nodes;
private int _nodeIndex; private int _nodeIndex;
private int _nextNodeIndex; private int _nextNodeIndex;
private int _count; private int _count;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator(BasketIterator iterator) public Enumerator(BasketIterator iterator)
{ {
ref BasketInfo basketInfo = ref iterator._basketList._baskets[iterator._basketIndex]; BasketNode* basketNode = iterator._basketList._basketNodePointers[iterator._basketIndex];
_nodes = iterator._basketList._nodes; _nodes = iterator._basketList._nodes;
_nodeIndex = -1; _nodeIndex = -1;
_nextNodeIndex = basketInfo.nodeIndex; _nextNodeIndex = basketNode->nodeIndex;
_count = basketInfo.count; _count = basketNode->count;
} }
public int Current public int Current
{ {
@ -351,33 +394,40 @@ namespace DCFApixels.DragonECS
get get
{ {
List<BasketIteratorDebbugerProxy> result = new List<BasketIteratorDebbugerProxy>(); List<BasketIteratorDebbugerProxy> result = new List<BasketIteratorDebbugerProxy>();
for (int i = 0; i < _basketList._baskets.Length; i++) for (int i = 0; i < _basketList._basketNodePointers.Length; i++)
{ {
if (_basketList._baskets[i].count > 0) if (_basketList._basketNodePointers[i] != BasketNode.EmptyInstancePtr)
{ {
result.Add(new BasketIteratorDebbugerProxy(_basketList[i])); result.Add(new BasketIteratorDebbugerProxy(i, _basketList[i]));
} }
} }
return result; return result;
} }
} }
public int RecycledListHead => _basketList._recycledListHead;
public IEnumerable<Node> Recycled public IEnumerable<Node> Recycled
{ {
get get
{ {
List<Node> result = new List<Node>(); List<Node> result = new List<Node>();
Node curNode = new Node(); Node curNode = new Node();
curNode.index = _basketList._recycledListLast; curNode.index = _basketList._recycledListHead;
while (curNode.index != -1) int i = 0;
while (curNode.index != NULL)
{ {
BasketList.Node x = _basketList.GetNode(curNode.index); BasketList.Node x = _basketList.GetNode(curNode.index);
curNode.prev = x.prev;
curNode.next = x.next; curNode.next = x.next;
result.Add(curNode); result.Add(curNode);
curNode = new Node(); if (i++ > _basketList._nodes.Length)
curNode.index = curNode.prev; {
result.Add(new Node(int.MinValue, int.MinValue, int.MinValue));
break;
}
curNode.index = curNode.next;
} }
return result; return result;
} }
@ -390,51 +440,97 @@ namespace DCFApixels.DragonECS
for (int i = 0; i < _basketList._nodes.Length; i++) for (int i = 0; i < _basketList._nodes.Length; i++)
{ {
result.Add(new Node(_basketList._nodes[i].prev, i, _basketList._nodes[i].next)); result.Add(new Node(i, _basketList._nodes[i].value, _basketList._nodes[i].next));
} }
return result; return result;
} }
} }
public Node[][] Chains
{
get
{
//bool IsChainLoop(int checkedNodeIndex)
//{
// bool result = false;
// int currentCheckedNodeIndex = checkedNodeIndex;
// for (int i = 0; i <= _basketList._nodes.Length; i++)
// {
// if (currentCheckedNodeIndex == 0)
// {
// result = true;
// }
// currentCheckedNodeIndex = _basketList._nodes[currentCheckedNodeIndex].next;
// }
// return result;
//}
List<Stack<int>> chains = new List<Stack<int>>();
for (int i = 1; i < _basketList._nodes.Length; i++)
{
if (_basketList._nodes[i].next == 0)
{
Stack<int> chain = new Stack<int>();
int lastNext = i;
chain.Push(lastNext);
for (int queueX = 1; queueX < _basketList._nodes.Length; queueX++)
{
for (int j = 1; j < _basketList._nodes.Length; j++)
{
var nodeJ = _basketList._nodes[j];
if(nodeJ.next == lastNext)
{
lastNext = j;
chain.Push(lastNext);
}
}
}
chains.Add(chain);
}
}
var nodes = _basketList._nodes;
return chains.Select(
o => o.Select(o => new Node(o, nodes[o].value, nodes[o].next)).ToArray()
).ToArray();
}
}
public DebuggerProxy(BasketList basketList) public DebuggerProxy(BasketList basketList)
{ {
_basketList = basketList; _basketList = basketList;
} }
public struct Node public struct Node
{ {
public int prev;
public int index; public int index;
public int value;
public int next; public int next;
public Node(int prev, int index, int next) public Node(int index, int value, int next)
{ {
this.prev = prev;
this.index = index; this.index = index;
this.value = value;
this.next = next; this.next = next;
} }
public override string ToString() => $"node({prev}< {index} >{next})"; public override string ToString() => $"[{index}] {value} >{next}";
} }
public struct BasketIteratorDebbugerProxy public struct BasketIteratorDebbugerProxy
{ {
public int index;
private BasketIterator _iterrator; private BasketIterator _iterrator;
public int Count => _iterrator.Count; public int Count => _iterrator.Count;
public IEnumerable<int> RelEntities public IEnumerable<int> RelEntities
{ {
get get
{ {
List<int> result = new List<int>(); List<int> result = new List<int>(_iterrator);
foreach (var e in _iterrator)
{
result.Add(e);
}
return result; return result;
} }
} }
public BasketIteratorDebbugerProxy(BasketIterator iterrator) public BasketIteratorDebbugerProxy(int index, BasketIterator iterrator)
{ {
this.index = index;
_iterrator = iterrator; _iterrator = iterrator;
} }
public override string ToString() public override string ToString()
{ {
return $"count: {_iterrator.Count}"; return $"[{index}] count: {_iterrator.Count}";
} }
} }
} }

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace DCFApixels.DragonECS.Relations.Internal namespace DCFApixels.DragonECS.Relations.Internal
{ {
@ -32,19 +33,27 @@ namespace DCFApixels.DragonECS.Relations.Internal
public ref T this[int index] public ref T this[int index]
{ {
get { return ref ptr[index]; } [MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
#if DEBUG
if (index < 0 || index >= Length)
Throw.ArgumentOutOfRange();
#endif
return ref ptr[index];
}
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray(int length) public UnsafeArray(int length)
{ {
UnmanagedArrayUtility.New(out ptr, length); ptr = UnmanagedArrayUtility.New<T>(length);
Length = length; Length = length;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray(int length, bool isInit) public UnsafeArray(int length, bool isInit)
{ {
UnmanagedArrayUtility.NewAndInit(out ptr, length); ptr = UnmanagedArrayUtility.NewAndInit<T>(length);
Length = length; Length = length;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -67,8 +76,7 @@ namespace DCFApixels.DragonECS.Relations.Internal
} }
public override string ToString() public override string ToString()
{ {
T* ptr = this.ptr; return $"ua({Length}) ({string.Join(", ", this.ToArray())})";
return CollectionUtility.AutoToString(EnumerableInt.Range(0, Length).Select(i => ptr[i]), "ua");
} }
public static void Resize(ref UnsafeArray<T> array, int newSize) public static void Resize(ref UnsafeArray<T> array, int newSize)
@ -113,12 +121,18 @@ namespace DCFApixels.DragonECS.Relations.Internal
internal class DebuggerProxy internal class DebuggerProxy
{ {
public void* ptr;
public T[] elements; public T[] elements;
public int length; public int length;
public DebuggerProxy(UnsafeArray<T> instance) public DebuggerProxy(UnsafeArray<T> instance)
{ {
elements = EnumerableInt.Range(0, instance.Length).Select(i => instance.ptr[i]).ToArray(); ptr = instance.ptr;
length = instance.Length; length = instance.Length;
elements = new T[length];
for (int i = 0; i < length; i++)
{
elements[i] = instance[i];
}
} }
} }
} }

View File

@ -0,0 +1,118 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS.Relations.Internal
{
internal unsafe static class UnsafePointersArray
{
public static void Resize<T>(ref UnsafePointersArray<T> array, int newSize)
where T : unmanaged
{
array.ptr = (T**)UnmanagedArrayUtility.Resize<IntPtr>(array.ptr, newSize);
array.Length = newSize;
}
public static void ResizeAndInit<T>(ref UnsafePointersArray<T> array, int newSize)
where T : unmanaged
{
array.ptr = (T**)UnmanagedArrayUtility.ResizeAndInit<IntPtr>(array.ptr, array.Length, newSize);
array.Length = newSize;
}
}
[DebuggerTypeProxy(typeof(UnsafePointersArray<>.DebuggerProxy))]
internal unsafe struct UnsafePointersArray<T> : IDisposable
where T : unmanaged
{
internal T** ptr;
internal int Length;
public ref T* this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
#if DEBUG
if (index < 0 || index >= Length)
Throw.ArgumentOutOfRange();
#endif
return ref ptr[index];
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafePointersArray(int length)
{
ptr = (T**)UnmanagedArrayUtility.New<IntPtr>(length);
Length = length;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafePointersArray(int length, bool isInit)
{
ptr = (T**)UnmanagedArrayUtility.NewAndInit<IntPtr>(length);
Length = length;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private UnsafePointersArray(T** ptr, int length)
{
this.ptr = ptr;
Length = length;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafePointersArray<T> Clone()
{
return new UnsafePointersArray<T>(UnmanagedArrayUtility.ClonePointersArray(ptr, Length), Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose()
{
UnmanagedArrayUtility.FreePointersArray(ref ptr, ref Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator() => new Enumerator(ptr, Length);
public struct Enumerator
{
private readonly T** _ptr;
private readonly int _length;
private int _index;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator(T** ptr, int length)
{
_ptr = ptr;
_length = length;
_index = -1;
}
public T* Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _ptr[_index];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext() => ++_index < _length;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset() { }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose() { }
}
internal class DebuggerProxy
{
public void* ptr;
public T*[] elements;
public int length;
public DebuggerProxy(UnsafePointersArray<T> instance)
{
ptr = instance.ptr;
length = instance.Length;
elements = new T*[length];
for (int i = 0; i < length; i++)
{
elements[i] = instance[i];
}
}
}
}
}