mirror of
https://github.com/DCFApixels/DragonECS-Graphs.git
synced 2025-09-18 11:54:35 +08:00
refactoring
This commit is contained in:
parent
35285d8064
commit
4c6e0ed045
@ -1,4 +1,4 @@
|
|||||||
using DCFApixels.DragonECS.Relations.Internal;
|
using DCFApixels.DragonECS.Graphs.Internal;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@ -223,8 +223,6 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
foreach (var relEntityID in relEntityBuffer)
|
foreach (var relEntityID in relEntityBuffer)
|
||||||
{
|
{
|
||||||
//var (startEntityID, endEntityID) = _arc._relEntityInfos[relEntityID];
|
|
||||||
//_arc.ClearRelation_Internal(startEntityID, endEntityID);
|
|
||||||
_arc.ClearRelation_Internal(relEntityID);
|
_arc.ClearRelation_Internal(relEntityID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,7 +240,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
_arc = arc;
|
_arc = arc;
|
||||||
_arc.StartWorld.AddListener(this);
|
_arc.StartWorld.AddListener(this);
|
||||||
OnWorldResize(_arc.StartWorld.Capacity);
|
//OnWorldResize(_arc.StartWorld.Capacity);
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
@ -264,7 +262,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
_arc = arc;
|
_arc = arc;
|
||||||
_arc.EndWorld.AddListener(this);
|
_arc.EndWorld.AddListener(this);
|
||||||
OnWorldResize(_arc.EndWorld.Capacity);
|
//OnWorldResize(_arc.EndWorld.Capacity);
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
@ -286,7 +284,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
_arc = arc;
|
_arc = arc;
|
||||||
_arc.StartWorld.AddListener(this);
|
_arc.StartWorld.AddListener(this);
|
||||||
OnWorldResize(_arc.StartWorld.Capacity);
|
//OnWorldResize(_arc.StartWorld.Capacity);
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public static class EcsWorldConfigRelationsExtensions
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
using DCFApixels.DragonECS.Relations.Internal;
|
using DCFApixels.DragonECS.Graphs.Internal;
|
||||||
using DCFApixels.DragonECS.Relations.Utils;
|
using DCFApixels.DragonECS.Graphs.Utils;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
|
@ -5,7 +5,7 @@ using System.Linq;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Relations.Internal
|
namespace DCFApixels.DragonECS.Graphs.Internal
|
||||||
{
|
{
|
||||||
internal static class ArrayUtility
|
internal static class ArrayUtility
|
||||||
{
|
{
|
@ -3,9 +3,9 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using static DCFApixels.DragonECS.Relations.Internal.BitsUtility;
|
using static DCFApixels.DragonECS.Graphs.Internal.BitsUtility;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Relations.Internal
|
namespace DCFApixels.DragonECS.Graphs.Internal
|
||||||
{
|
{
|
||||||
internal unsafe static class BitsUtility
|
internal unsafe static class BitsUtility
|
||||||
{
|
{
|
@ -2,11 +2,11 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS.Graphs.Internal
|
||||||
{
|
{
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public readonly struct RelEntityInfo : IEquatable<RelEntityInfo>
|
internal readonly struct RelEntityInfo : IEquatable<RelEntityInfo>
|
||||||
{
|
{
|
||||||
public static readonly RelEntityInfo Empty = new RelEntityInfo();
|
public static readonly RelEntityInfo Empty = new RelEntityInfo();
|
||||||
|
|
@ -6,9 +6,9 @@ using System.Diagnostics.Contracts;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Relations.Utils
|
namespace DCFApixels.DragonECS.Graphs.Internal
|
||||||
{
|
{
|
||||||
public class SparseArray<TValue>
|
internal class SparseArray<TValue>
|
||||||
{
|
{
|
||||||
public const int MIN_CAPACITY_BITS_OFFSET = 4;
|
public const int MIN_CAPACITY_BITS_OFFSET = 4;
|
||||||
public const int MIN_CAPACITY = 1 << MIN_CAPACITY_BITS_OFFSET;
|
public const int MIN_CAPACITY = 1 << MIN_CAPACITY_BITS_OFFSET;
|
@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using TValue = System.Int32;
|
using TValue = System.Int32;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Relations.Internal
|
namespace DCFApixels.DragonECS.Graphs.Internal
|
||||||
{
|
{
|
||||||
internal sealed unsafe class SparseMatrix
|
internal sealed unsafe class SparseMatrix
|
||||||
{
|
{
|
||||||
@ -33,7 +33,6 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
public int Capacity
|
public int Capacity
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
//get { return _buckets.Length; }
|
|
||||||
get { return _capacity; }
|
get { return _capacity; }
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -43,15 +42,11 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
public SparseMatrix(int minCapacity = MIN_CAPACITY)
|
public SparseMatrix(int minCapacity = MIN_CAPACITY)
|
||||||
{
|
{
|
||||||
minCapacity = NormalizeCapacity(minCapacity);
|
minCapacity = NormalizeCapacity(minCapacity);
|
||||||
//_buckets = new Basket[minCapacity];
|
|
||||||
//_buckets = new UnsafeArray<Basket>(minCapacity);
|
|
||||||
_buckets = UnmanagedArrayUtility.New<Basket>(minCapacity);
|
_buckets = UnmanagedArrayUtility.New<Basket>(minCapacity);
|
||||||
for (int i = 0; i < minCapacity; i++)
|
for (int i = 0; i < minCapacity; i++)
|
||||||
{
|
{
|
||||||
_buckets[i] = Basket.Empty;
|
_buckets[i] = Basket.Empty;
|
||||||
}
|
}
|
||||||
//_entries = new Entry[minCapacity];
|
|
||||||
//_entries = new UnsafeArray<Entry>(minCapacity, true);
|
|
||||||
_entries = UnmanagedArrayUtility.NewAndInit<Entry>(minCapacity);
|
_entries = UnmanagedArrayUtility.NewAndInit<Entry>(minCapacity);
|
||||||
_modBitMask = (minCapacity - 1) & 0x7FFFFFFF;
|
_modBitMask = (minCapacity - 1) & 0x7FFFFFFF;
|
||||||
|
|
||||||
@ -59,13 +54,10 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
_freeList = 0;
|
_freeList = 0;
|
||||||
_freeCount = 0;
|
_freeCount = 0;
|
||||||
|
|
||||||
//
|
|
||||||
_capacity = minCapacity;
|
_capacity = minCapacity;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region Add/TryAdd/Set
|
#region Add/TryAdd/Set
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void Add(int x, int y, TValue value)
|
public void Add(int x, int y, TValue value)
|
||||||
@ -74,7 +66,7 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (FindEntry(key) >= 0)
|
if (FindEntry(key) >= 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Has(x, y) is true");
|
Throw.ArgumentException("Has(x, y) is true");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
int targetBucket = key.yHash & _modBitMask;
|
int targetBucket = key.yHash & _modBitMask;
|
||||||
@ -114,7 +106,6 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
int index;
|
int index;
|
||||||
if (_freeCount == 0)
|
if (_freeCount == 0)
|
||||||
{
|
{
|
||||||
//if (_count == _entries.Length)
|
|
||||||
if (_count == _capacity)
|
if (_count == _capacity)
|
||||||
{
|
{
|
||||||
Resize();
|
Resize();
|
||||||
@ -124,26 +115,23 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//_freeCount > 0
|
|
||||||
index = _freeList;
|
index = _freeList;
|
||||||
_freeList = _entries[index].next;
|
_freeList = _entries[index].next;
|
||||||
_freeCount--;
|
_freeCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if(_freeCount < 0) { throw new Exception(); }
|
if(_freeCount < 0) { Throw.UndefinedException(); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ref Basket basket = ref _buckets[targetBucket];
|
ref Basket basket = ref _buckets[targetBucket];
|
||||||
ref Entry entry = ref _entries[index];
|
ref Entry entry = ref _entries[index];
|
||||||
|
|
||||||
|
|
||||||
entry.next = basket.index;
|
entry.next = basket.index;
|
||||||
entry.key = key;
|
entry.key = key;
|
||||||
entry.value = value;
|
entry.value = value;
|
||||||
basket.count++;
|
basket.count++;
|
||||||
basket.index = index;
|
basket.index = index;
|
||||||
//Console.WriteLine($"{targetBucket} {basket.count}");
|
|
||||||
|
|
||||||
if (basket.count >= MAX_CHAIN_LENGTH && Count / Capacity >= 0.7f)
|
if (basket.count >= MAX_CHAIN_LENGTH && Count / Capacity >= 0.7f)
|
||||||
{
|
{
|
||||||
@ -191,10 +179,7 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
{
|
{
|
||||||
int index = FindEntry(x, y);
|
int index = FindEntry(x, y);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if(index < 0)
|
if(index < 0) { Throw.KeyNotFound(); }
|
||||||
{
|
|
||||||
throw new KeyNotFoundException();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return _entries[index].value;
|
return _entries[index].value;
|
||||||
}
|
}
|
||||||
@ -246,21 +231,15 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region Clear
|
#region Clear
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
if (_count > 0)
|
if (_count > 0)
|
||||||
{
|
{
|
||||||
//for (int i = 0; i < _buckets.Length; i++)
|
|
||||||
for (int i = 0; i < _capacity; i++)
|
for (int i = 0; i < _capacity; i++)
|
||||||
{
|
{
|
||||||
_buckets[i] = Basket.Empty;
|
_buckets[i] = Basket.Empty;
|
||||||
}
|
}
|
||||||
//Array.Clear(_entries, 0, _count);
|
|
||||||
//UnsafeArray.Clear(ref _entries);
|
|
||||||
for (int i = 0; i < _capacity; i++)
|
for (int i = 0; i < _capacity; i++)
|
||||||
{
|
{
|
||||||
_entries[i] = default;
|
_entries[i] = default;
|
||||||
@ -274,26 +253,16 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
private void Resize()
|
private void Resize()
|
||||||
{
|
{
|
||||||
//int newSize = _buckets.Length << 1;
|
|
||||||
int newSize = _capacity << 1;
|
int newSize = _capacity << 1;
|
||||||
_modBitMask = (newSize - 1) & 0x7FFFFFFF;
|
_modBitMask = (newSize - 1) & 0x7FFFFFFF;
|
||||||
|
|
||||||
//Contract.Assert(newSize >= _entries.Length);
|
|
||||||
|
|
||||||
//Basket[] newBuckets = new Basket[newSize];
|
|
||||||
//UnsafeArray<Basket> newBuckets = new UnsafeArray<Basket>(newSize);
|
|
||||||
Basket* newBuckets = UnmanagedArrayUtility.New<Basket>(newSize);
|
Basket* newBuckets = UnmanagedArrayUtility.New<Basket>(newSize);
|
||||||
//for (int i = 0; i < newBuckets.Length; i++)
|
|
||||||
for (int i = 0; i < _capacity; i++)
|
for (int i = 0; i < _capacity; i++)
|
||||||
{
|
{
|
||||||
newBuckets[i] = Basket.Empty;
|
newBuckets[i] = Basket.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Entry[] newEntries = new Entry[newSize];
|
|
||||||
//Array.Copy(_entries, 0, newEntries, 0, _count);
|
|
||||||
//UnsafeArray<Entry> newEntries = UnsafeArray<Entry>.Resize(_entries, newSize);
|
|
||||||
Entry* newEntries = UnmanagedArrayUtility.ResizeAndInit<Entry>(_entries, _capacity, newSize);
|
Entry* newEntries = UnmanagedArrayUtility.ResizeAndInit<Entry>(_entries, _capacity, newSize);
|
||||||
|
|
||||||
for (int i = 0; i < _count; i++)
|
for (int i = 0; i < _count; i++)
|
||||||
{
|
{
|
||||||
if (newEntries[i].key.yHash >= 0)
|
if (newEntries[i].key.yHash >= 0)
|
||||||
@ -309,8 +278,6 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
_entries = newEntries;
|
_entries = newEntries;
|
||||||
|
|
||||||
_capacity = newSize;
|
_capacity = newSize;
|
||||||
|
|
||||||
Console.WriteLine($"----- {Capacity} {Count}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@ -329,18 +296,13 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
public int next; // Index of next entry, -1 if last
|
public int next; // Index of next entry, -1 if last
|
||||||
public Key key;
|
public Key key;
|
||||||
public TValue value;
|
public TValue value;
|
||||||
|
public override string ToString() { return key.x == 0 ? "NULL" : value.ToString(); }
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return key.x == 0 ? "NULL" : value.ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
||||||
public struct Basket
|
public struct Basket
|
||||||
{
|
{
|
||||||
public static readonly Basket Empty = new Basket(-1, 0);
|
public static readonly Basket Empty = new Basket(-1, 0);
|
||||||
|
|
||||||
public int index;
|
public int index;
|
||||||
public int count;
|
public int count;
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@ -349,10 +311,7 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
this.index = index;
|
this.index = index;
|
||||||
this.count = length;
|
this.count = length;
|
||||||
}
|
}
|
||||||
public override string ToString()
|
public override string ToString() { return index < 0 ? "NULL" : $"{index} {count}"; }
|
||||||
{
|
|
||||||
return index < 0 ? "NULL" : $"{index} {count}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
||||||
@ -368,32 +327,12 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
this.yHash = yHash;
|
this.yHash = yHash;
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Key FromXY(int x, int y)
|
public static Key FromXY(int x, int y) { return new Key(x, x ^ y ^ BitsUtility.NextXorShiftState(y)); }
|
||||||
{
|
public static bool operator ==(Key a, Key b) { return a.x == b.x && a.yHash == b.yHash; }
|
||||||
//return new Key(x, BitsUtility.NextXorShiftState(y));
|
public static bool operator !=(Key a, Key b) { return a.x != b.x || a.yHash != b.yHash; }
|
||||||
//return new Key(x, (~x) ^ y ^ 1_431_655_765);
|
public override int GetHashCode() { return yHash; }
|
||||||
return new Key(x, x ^ y ^ BitsUtility.NextXorShiftState(y));
|
public bool Equals(Key other) { return this == other; }
|
||||||
}
|
public override bool Equals(object obj) { return obj is Key && Equals((Key)obj); }
|
||||||
public static bool operator ==(Key a, Key b)
|
|
||||||
{
|
|
||||||
return a.x == b.x && a.yHash == b.yHash;
|
|
||||||
}
|
|
||||||
public static bool operator !=(Key a, Key b)
|
|
||||||
{
|
|
||||||
return a.x != b.x || a.yHash != b.yHash;
|
|
||||||
}
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return yHash;
|
|
||||||
}
|
|
||||||
public bool Equals(Key other)
|
|
||||||
{
|
|
||||||
return this == other;
|
|
||||||
}
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
return obj is Key && Equals((Key)obj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ using System.Diagnostics;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Relations.Internal
|
namespace DCFApixels.DragonECS.Graphs.Internal
|
||||||
{
|
{
|
||||||
internal unsafe static class UnsafeArray
|
internal unsafe static class UnsafeArray
|
||||||
{
|
{
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 57bb7865029f870429c7b698334b116f
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,34 +1,52 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Relations.Internal
|
namespace DCFApixels.DragonECS.Graphs.Internal
|
||||||
{
|
{
|
||||||
internal static class Throw
|
internal static class Throw
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
internal static void RelationAlreadyExists()
|
||||||
|
{
|
||||||
|
throw new EcsRelationException("This relation already exists.");
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
internal static void UndefinedRelationException()
|
||||||
|
{
|
||||||
|
throw new EcsRelationException();
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static void ArgumentNull()
|
internal static void ArgumentNull()
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException();
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
internal static void ArgumentOutOfRange()
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException($"index is less than 0 or is equal to or greater than Count.");
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static void UndefinedException()
|
internal static void UndefinedException()
|
||||||
{
|
{
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static void ArgumentOutOfRange()
|
internal static void Exception(string message)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new Exception(message);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static void UndefinedRelationException()
|
internal static void ArgumentException(string message)
|
||||||
{
|
{
|
||||||
throw new EcsRelationException();
|
throw new ArgumentException(message);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static void RelationAlreadyExists()
|
internal static void KeyNotFound()
|
||||||
{
|
{
|
||||||
throw new EcsRelationException("This relation already exists.");
|
throw new KeyNotFoundException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e369fe57852b216439940cad19bbb5f2
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5c8028c38ac28f84eac2ee5238fc3c2a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: cdd3589bd2d514845b172b2952fccc81
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,265 +0,0 @@
|
|||||||
//SparseArray64. Analogous to Dictionary<long, T>, but faster.
|
|
||||||
//Benchmark result of indexer.get speed test with 300 elements:
|
|
||||||
//[Dictinary: 6.705us] [SparseArray64: 2.512us].
|
|
||||||
using DCFApixels.DragonECS.Relations.Internal;
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Diagnostics.Contracts;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Relations.Utils
|
|
||||||
{
|
|
||||||
internal unsafe class SparseArray64<TValue>
|
|
||||||
where TValue : unmanaged
|
|
||||||
{
|
|
||||||
public const int MIN_CAPACITY_BITS_OFFSET = 4;
|
|
||||||
public const int MIN_CAPACITY = 1 << MIN_CAPACITY_BITS_OFFSET;
|
|
||||||
private const int EMPTY = -1;
|
|
||||||
|
|
||||||
private UnsafeArray<int> _buckets;
|
|
||||||
private UnsafeArray<Entry> _entries;
|
|
||||||
|
|
||||||
private int _count;
|
|
||||||
|
|
||||||
private int _freeList;
|
|
||||||
private int _freeCount;
|
|
||||||
|
|
||||||
private int _modBitMask;
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public TValue this[long keyX, long keyY]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
//TODO Проверить необходимость проверки на Null
|
|
||||||
return _entries.ptr[FindEntry(keyX + (keyY << 32))].value;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Insert(keyX + (keyY << 32), value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public TValue this[long key]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
//TODO Проверить необходимость проверки на Null
|
|
||||||
return _entries.ptr[FindEntry(key)].value;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Insert(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Count
|
|
||||||
{
|
|
||||||
get { return _count; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
public SparseArray64(int minCapacity = MIN_CAPACITY)
|
|
||||||
{
|
|
||||||
minCapacity = NormalizeCapacity(minCapacity);
|
|
||||||
_buckets = new UnsafeArray<int>(minCapacity);
|
|
||||||
for (int i = 0; i < minCapacity; i++)
|
|
||||||
{
|
|
||||||
_buckets[i] = EMPTY;
|
|
||||||
}
|
|
||||||
_entries = new UnsafeArray<Entry>(minCapacity);
|
|
||||||
_modBitMask = (minCapacity - 1) & 0x7FFFFFFF;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Add
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Add(long keyX, long keyY, TValue value) => Add(keyX + (keyY << 32), value);
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Add(long key, TValue value)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
if (Contains(key))
|
|
||||||
throw new ArgumentException("Contains(hashKey) is true");
|
|
||||||
#endif
|
|
||||||
Insert(key, value);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Find/Insert/Remove
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private int FindEntry(long key)
|
|
||||||
{
|
|
||||||
for (int i = _buckets[unchecked((int)key & _modBitMask)]; i >= 0; i = _entries[i].next)
|
|
||||||
if (_entries[i].hashKey == key) return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
private void Insert(long key, TValue value)
|
|
||||||
{
|
|
||||||
int targetBucket = unchecked((int)key & _modBitMask);
|
|
||||||
|
|
||||||
for (int i = _buckets[targetBucket]; i >= 0; i = _entries[i].next)
|
|
||||||
{
|
|
||||||
if (_entries[i].hashKey == key)
|
|
||||||
{
|
|
||||||
_entries[i].value = value;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int index;
|
|
||||||
if (_freeCount > 0)
|
|
||||||
{
|
|
||||||
index = _freeList;
|
|
||||||
_freeList = _entries[index].next;
|
|
||||||
_freeCount--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_count == _entries.Length)
|
|
||||||
{
|
|
||||||
Resize();
|
|
||||||
targetBucket = unchecked((int)key & _modBitMask);
|
|
||||||
}
|
|
||||||
index = _count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_entries[index].next = _buckets[targetBucket];
|
|
||||||
_entries[index].hashKey = key;
|
|
||||||
_entries[index].value = value;
|
|
||||||
_buckets[targetBucket] = index;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool Remove(long keyX, long keyY) => Remove(keyX + (keyY << 32));
|
|
||||||
public bool Remove(long key)
|
|
||||||
{
|
|
||||||
int bucket = unchecked((int)key & _modBitMask);
|
|
||||||
int last = -1;
|
|
||||||
for (int i = _buckets[bucket]; i >= 0; last = i, i = _entries[i].next)
|
|
||||||
{
|
|
||||||
if (_entries[i].hashKey == key)
|
|
||||||
{
|
|
||||||
if (last < 0)
|
|
||||||
{
|
|
||||||
_buckets[bucket] = _entries[i].next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_entries[last].next = _entries[i].next;
|
|
||||||
}
|
|
||||||
_entries[i].next = _freeList;
|
|
||||||
_entries[i].hashKey = -1;
|
|
||||||
_entries[i].value = default;
|
|
||||||
_freeList = i;
|
|
||||||
_freeCount++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region TryGetValue
|
|
||||||
public bool TryGetValue(long key, out TValue value)
|
|
||||||
{
|
|
||||||
int index = FindEntry(key);
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
value = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
value = _entries.ptr[index].value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public bool TryGetValue(long keyX, long keyY, out TValue value)
|
|
||||||
{
|
|
||||||
int index = FindEntry(keyX + (keyY << 32));
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
value = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
value = _entries.ptr[index].value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Contains
|
|
||||||
public bool Contains(long keyX, long keyY)
|
|
||||||
{
|
|
||||||
return FindEntry(keyX + (keyY << 32)) >= 0;
|
|
||||||
}
|
|
||||||
public bool Contains(long key)
|
|
||||||
{
|
|
||||||
return FindEntry(key) >= 0;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Clear
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
if (_count > 0)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < _buckets.Length; i++)
|
|
||||||
{
|
|
||||||
_buckets[i] = -1;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < _count; i++)
|
|
||||||
{
|
|
||||||
_entries[i] = default;
|
|
||||||
}
|
|
||||||
_count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Resize
|
|
||||||
private void Resize()
|
|
||||||
{
|
|
||||||
int newSize = _buckets.Length << 1;
|
|
||||||
_modBitMask = (newSize - 1) & 0x7FFFFFFF;
|
|
||||||
|
|
||||||
Contract.Assert(newSize >= _entries.Length);
|
|
||||||
UnsafeArray<int> newBuckets = new UnsafeArray<int>(newSize);
|
|
||||||
for (int i = 0; i < newBuckets.Length; i++)
|
|
||||||
newBuckets[i] = EMPTY;
|
|
||||||
|
|
||||||
UnsafeArray<Entry> newEntries = UnsafeArray<Entry>.Resize(_entries, newSize);
|
|
||||||
//UnsafeArray<Entry> newEntries = new UnsafeArray<Entry>(newSize);
|
|
||||||
//Array.Copy(_entries, 0, newEntries, 0, _count);
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < _count; i++)
|
|
||||||
{
|
|
||||||
if (newEntries[i].hashKey >= 0)
|
|
||||||
{
|
|
||||||
int bucket = unchecked((int)newEntries[i].hashKey & _modBitMask);
|
|
||||||
newEntries[i].next = newBuckets[bucket];
|
|
||||||
newBuckets[bucket] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_buckets = newBuckets;
|
|
||||||
_entries = newEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int NormalizeCapacity(int capacity)
|
|
||||||
{
|
|
||||||
int result = MIN_CAPACITY;
|
|
||||||
while (result < capacity) result <<= 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Utils
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
|
||||||
[DebuggerDisplay("next{next} hashKey{hashKey} value{value}")]
|
|
||||||
private struct Entry
|
|
||||||
{
|
|
||||||
public int next; // Index of next entry, -1 if last
|
|
||||||
public long hashKey;
|
|
||||||
public TValue value;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a5614297928ccbc479e9a0b7bd42df4b
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
Loading…
Reference in New Issue
Block a user