mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2026-04-22 01:45:55 +08:00
remove span dummy/update&fix alloc management/add EcsUnsafeSpan & WhereUnsafe
This commit is contained in:
parent
14bf846135
commit
c30d4ec5f0
@ -196,7 +196,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
if (_groupSparsePagePoolCount <= 0)
|
||||
{
|
||||
return MemoryAllocator.AllocAndInit<int>(EcsGroup.PAGE_SIZE).As<int>();
|
||||
return MemoryAllocator.AllocAndInit<int>(EcsGroup.PAGE_SIZE).Ptr;
|
||||
}
|
||||
var takedPage = _groupSparsePagePool[--_groupSparsePagePoolCount];
|
||||
_groupSparsePagePool[_groupSparsePagePoolCount] = MemoryAllocator.Handler.Empty;
|
||||
@ -228,7 +228,7 @@ namespace DCFApixels.DragonECS
|
||||
for (int i = 0; i < _groupSparsePagePoolCount; i++)
|
||||
{
|
||||
ref var page = ref _groupSparsePagePool[i];
|
||||
if (page.IsEmpty == false)
|
||||
if (page.IsCreated)
|
||||
{
|
||||
MemoryAllocator.FreeAndClear(ref page);
|
||||
}
|
||||
@ -291,7 +291,7 @@ namespace DCFApixels.DragonECS
|
||||
private int _count = 0;
|
||||
internal bool _isReleased = true;
|
||||
|
||||
internal static readonly int* _nullPage = MemoryAllocator.AllocAndInit<int>(PageSlot.SIZE).As<int>();
|
||||
internal static readonly int* _nullPage = MemoryAllocator.AllocAndInit<int>(PageSlot.SIZE).Ptr;
|
||||
internal static readonly long _nullPagePtrFake = (long)_nullPage;
|
||||
|
||||
#region Properties
|
||||
@ -344,17 +344,6 @@ namespace DCFApixels.DragonECS
|
||||
#endif
|
||||
return _dense[++index];
|
||||
}
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// set
|
||||
// {
|
||||
// // TODO добавить лок енумератора на изменение
|
||||
//#if DEBUG || DRAGONECS_STABILITY_MODE
|
||||
// if (index < 0 || index >= Count) { Throw.ArgumentOutOfRange(); }
|
||||
//#endif
|
||||
// var oldValue = _dense[index];
|
||||
// _dense[index] = value;
|
||||
// _sparse[oldValue] = 0;
|
||||
// }
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -394,7 +383,7 @@ namespace DCFApixels.DragonECS
|
||||
page.IndexesXOR = 0;
|
||||
page.Count = 0;
|
||||
}
|
||||
_sparsePagesHandler.Dispose();
|
||||
_sparsePagesHandler.DisposeAndReset();
|
||||
}
|
||||
}
|
||||
public void Dispose()
|
||||
@ -555,7 +544,6 @@ namespace DCFApixels.DragonECS
|
||||
ref PageSlot page = ref _sparsePages[i];
|
||||
if (page.Indexes != _nullPage)
|
||||
{
|
||||
//TODO тут надо оптимизировать отчисткой не всего а по dense списку
|
||||
for (int j = 0; j < PageSlot.SIZE; j++)
|
||||
{
|
||||
page.Indexes[j] = 0;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#if DISABLE_DEBUG
|
||||
#undef DEBUG
|
||||
#endif
|
||||
using DCFApixels.DragonECS.Core;
|
||||
using DCFApixels.DragonECS.Core.Internal;
|
||||
using DCFApixels.DragonECS.Core.Unchecked;
|
||||
using System;
|
||||
@ -127,6 +128,7 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
public ReadOnlySpan<int> AsSystemSpan() { return _values; }
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int First() { return _values[0]; }
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@ -170,6 +172,7 @@ namespace DCFApixels.DragonECS
|
||||
_worldID = span._worldID;
|
||||
}
|
||||
public DebuggerProxy(EcsLongsSpan span) : this(span.ToSpan()) { }
|
||||
public DebuggerProxy(EcsUnsafeSpan span) : this(span.ToSpan()) { }
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@ -317,3 +320,164 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
namespace DCFApixels.DragonECS.Core
|
||||
{
|
||||
#if ENABLE_IL2CPP
|
||||
using Unity.IL2CPP.CompilerServices;
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
#endif
|
||||
[DebuggerTypeProxy(typeof(EcsSpan.DebuggerProxy))]
|
||||
public unsafe readonly struct EcsUnsafeSpan
|
||||
{
|
||||
private readonly int* _values;
|
||||
private readonly int _length;
|
||||
private readonly short _worldID;
|
||||
|
||||
#region Properties
|
||||
public bool IsNull
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _worldID == 0; }
|
||||
}
|
||||
public short WorldID
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _worldID; }
|
||||
}
|
||||
public EcsWorld World
|
||||
{
|
||||
get { return EcsWorld.GetWorld(_worldID); }
|
||||
}
|
||||
public int Count
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _length; }
|
||||
}
|
||||
public EcsLongsSpan Longs
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return ToSpan().Longs; }
|
||||
}
|
||||
public bool IsSourceEntities
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return ToSpan() == EcsWorld.GetWorld(_worldID).GetCurrentEntities_Internal(); }
|
||||
}
|
||||
|
||||
public int this[int index]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
if ((uint)index >= (uint)_length || (uint)index < 0)
|
||||
{
|
||||
ThrowHelper.ThrowIndexOutOfRangeException();
|
||||
}
|
||||
#elif DRAGONECS_STABILITY_MODE
|
||||
return EcsConsts.NULL_ENTITY_ID;
|
||||
#endif
|
||||
return _values[index];
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
internal EcsUnsafeSpan(short worldID, int* array, int length)
|
||||
{
|
||||
_worldID = worldID;
|
||||
_values = array;
|
||||
_length = length;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal EcsUnsafeSpan(short worldID, int* array, int start, int length)
|
||||
{
|
||||
_worldID = worldID;
|
||||
_values = array + start;
|
||||
_length = length;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Slice/ToArray
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public EcsUnsafeSpan Slice(int start)
|
||||
{
|
||||
if ((uint)start > (uint)_length)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException();
|
||||
}
|
||||
return new EcsUnsafeSpan(_worldID, _values, start, _length - start);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public EcsUnsafeSpan Slice(int start, int length)
|
||||
{
|
||||
if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException();
|
||||
}
|
||||
return new EcsUnsafeSpan(_worldID, _values, start, length);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public EcsSpan ToSpan() { return new EcsSpan(_worldID, new ReadOnlySpan<int>(_values, _length)); }
|
||||
public int[] ToArray() { return new ReadOnlySpan<int>(_values, _length).ToArray(); }
|
||||
public int ToArray(ref int[] dynamicBuffer)
|
||||
{
|
||||
if (dynamicBuffer.Length < _length)
|
||||
{
|
||||
Array.Resize(ref dynamicBuffer, ArrayUtility.CeilPow2(_length));
|
||||
}
|
||||
int i = 0;
|
||||
foreach (var e in this)
|
||||
{
|
||||
dynamicBuffer[i++] = e;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
public void ToCollection(ICollection<int> collection)
|
||||
{
|
||||
foreach (var e in this)
|
||||
{
|
||||
collection.Add(e);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region operators
|
||||
public static bool operator ==(EcsUnsafeSpan left, EcsUnsafeSpan right) { return left._values == right._values; }
|
||||
public static bool operator !=(EcsUnsafeSpan left, EcsUnsafeSpan right) { return left._values != right._values; }
|
||||
public static implicit operator EcsSpan(EcsUnsafeSpan a) { return a.ToSpan(); }
|
||||
#endregion
|
||||
|
||||
#region Enumerator
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ReadOnlySpan<int>.Enumerator GetEnumerator() { return new ReadOnlySpan<int>(_values, _length).GetEnumerator(); }
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int First() { return _values[0]; }
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Last() { return _values[_length - 1]; }
|
||||
public override string ToString()
|
||||
{
|
||||
return CollectionUtility.EntitiesToString(ToArray(), "span");
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is EcsUnsafeSpan other && other == this;
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return *_values ^ _length ^ (_worldID << 16);
|
||||
}
|
||||
private static class ThrowHelper
|
||||
{
|
||||
public static void ThrowIndexOutOfRangeException() => throw new IndexOutOfRangeException();
|
||||
public static void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException();
|
||||
public static void ThrowInvalidOperationException() => throw new InvalidOperationException();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -615,8 +615,8 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
private void Cleanup(bool disposing)
|
||||
{
|
||||
_bufferHandler.Dispose();
|
||||
_chunckBufferHandler.Dispose();
|
||||
_bufferHandler.DisposeAndReset();
|
||||
_chunckBufferHandler.DisposeAndReset();
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -644,8 +644,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
if (_sortIncChunckBuffer.Length > 1)
|
||||
{
|
||||
var comparer = new IncCountComparer(counts);
|
||||
UnsafeArraySortHalperX<int>.InsertionSort(sortIncBuffer.ptr, sortIncBuffer.Length, ref comparer);
|
||||
sortIncBuffer.AsSpan().Sort(new IncCountComparer(counts));
|
||||
ConvertToChuncks(preSortingBuffer, sortIncBuffer, _sortIncChunckBuffer);
|
||||
}
|
||||
if (_sortIncChunckBuffer.Length > 0)
|
||||
@ -659,8 +658,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
if (_sortExcChunckBuffer.Length > 1)
|
||||
{
|
||||
ExcCountComparer comparer = new ExcCountComparer(counts);
|
||||
UnsafeArraySortHalperX<int>.InsertionSort(sortExcBuffer.ptr, sortExcBuffer.Length, ref comparer);
|
||||
sortExcBuffer.AsSpan().Sort(new ExcCountComparer(counts));
|
||||
ConvertToChuncks(preSortingBuffer, sortExcBuffer, _sortExcChunckBuffer);
|
||||
}
|
||||
// Выражение IncCount < (AllEntitesCount - ExcCount) мало вероятно будет истинным.
|
||||
@ -670,8 +668,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
if (_sortAnyChunckBuffer.Length > 1)
|
||||
{
|
||||
ExcCountComparer comparer = new ExcCountComparer(counts);
|
||||
UnsafeArraySortHalperX<int>.InsertionSort(sortAnyBuffer.ptr, sortAnyBuffer.Length, ref comparer);
|
||||
sortAnyBuffer.AsSpan().Sort(new ExcCountComparer(counts));
|
||||
ConvertToChuncks(preSortingBuffer, sortAnyBuffer, _sortAnyChunckBuffer);
|
||||
}
|
||||
// Any не влияет на maxEntites если есть Inc и сложно высчитывается если нет Inc
|
||||
@ -699,9 +696,13 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region IterateTo
|
||||
//TODO Перемеиноваться в CacheTo
|
||||
public EcsMaskFlags MaskFlags
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void IterateTo(EcsSpan source, EcsGroup group)
|
||||
get { return _maskFlags; }
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void CacheTo(EcsSpan source, EcsGroup group)
|
||||
{
|
||||
switch (_maskFlags)
|
||||
{
|
||||
@ -709,7 +710,7 @@ namespace DCFApixels.DragonECS
|
||||
group.CopyFrom(source);
|
||||
break;
|
||||
case EcsMaskFlags.Inc:
|
||||
IterateOnlyInc(source).CopyTo(group);
|
||||
IterateOnlyInc(source).CacheTo(group);
|
||||
break;
|
||||
case EcsMaskFlags.Exc:
|
||||
case EcsMaskFlags.Any:
|
||||
@ -717,7 +718,7 @@ namespace DCFApixels.DragonECS
|
||||
case EcsMaskFlags.IncAny:
|
||||
case EcsMaskFlags.ExcAny:
|
||||
case EcsMaskFlags.IncExcAny:
|
||||
Iterate(source).CopyTo(group);
|
||||
Iterate(source).CacheTo(group);
|
||||
break;
|
||||
case EcsMaskFlags.Broken:
|
||||
group.Clear();
|
||||
@ -728,21 +729,21 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int IterateTo(EcsSpan source, ref int[] array)
|
||||
public int CacheTo(EcsSpan source, ref int[] array)
|
||||
{
|
||||
switch (_maskFlags)
|
||||
{
|
||||
case EcsMaskFlags.Empty:
|
||||
return source.ToArray(ref array);
|
||||
case EcsMaskFlags.Inc:
|
||||
return IterateOnlyInc(source).CopyTo(ref array);
|
||||
return IterateOnlyInc(source).CacheTo(ref array);
|
||||
case EcsMaskFlags.Exc:
|
||||
case EcsMaskFlags.Any:
|
||||
case EcsMaskFlags.IncExc:
|
||||
case EcsMaskFlags.IncAny:
|
||||
case EcsMaskFlags.ExcAny:
|
||||
case EcsMaskFlags.IncExcAny:
|
||||
return Iterate(source).CopyTo(ref array);
|
||||
return Iterate(source).CacheTo(ref array);
|
||||
case EcsMaskFlags.Broken:
|
||||
return new EcsSpan(World.ID, Array.Empty<int>()).ToArray(ref array);
|
||||
default:
|
||||
@ -772,7 +773,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region CopyTo
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void CopyTo(EcsGroup group)
|
||||
public void CacheTo(EcsGroup group)
|
||||
{
|
||||
group.Clear();
|
||||
var enumerator = GetEnumerator();
|
||||
@ -782,7 +783,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int CopyTo(ref int[] array)
|
||||
public int CacheTo(ref int[] array)
|
||||
{
|
||||
int count = 0;
|
||||
var enumerator = GetEnumerator();
|
||||
@ -928,7 +929,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region CopyTo
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void CopyTo(EcsGroup group)
|
||||
public void CacheTo(EcsGroup group)
|
||||
{
|
||||
group.Clear();
|
||||
var enumerator = GetEnumerator();
|
||||
@ -938,7 +939,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int CopyTo(ref int[] array)
|
||||
public int CacheTo(ref int[] array)
|
||||
{
|
||||
int count = 0;
|
||||
var enumerator = GetEnumerator();
|
||||
|
||||
@ -698,7 +698,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
else
|
||||
{
|
||||
poolIdsPtr = UnmanagedArrayUtility.New<int>(count);
|
||||
poolIdsPtr = MemoryAllocator.Alloc<int>(count).Ptr;
|
||||
}
|
||||
|
||||
UnsafeArray<int> ua = UnsafeArray<int>.Manual(poolIdsPtr, count);
|
||||
@ -711,7 +711,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
if (count >= BUFFER_THRESHOLD)
|
||||
{
|
||||
UnmanagedArrayUtility.Free(poolIdsPtr);
|
||||
MemoryAllocator.Free(poolIdsPtr);
|
||||
}
|
||||
|
||||
|
||||
@ -748,7 +748,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
else
|
||||
{
|
||||
poolIdsPtr = UnmanagedArrayUtility.New<int>(count);
|
||||
poolIdsPtr = MemoryAllocator.Alloc<int>(count).Ptr;
|
||||
}
|
||||
|
||||
GetComponentTypeIDsFor_Internal(fromEntityID, poolIdsPtr, count);
|
||||
@ -759,7 +759,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
if (count >= BUFFER_THRESHOLD)
|
||||
{
|
||||
UnmanagedArrayUtility.Free(poolIdsPtr);
|
||||
MemoryAllocator.Free(poolIdsPtr);
|
||||
}
|
||||
|
||||
//foreach (var pool in _pools)
|
||||
@ -1082,7 +1082,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
else
|
||||
{
|
||||
poolIdsPtr = UnmanagedArrayUtility.New<int>(count);
|
||||
poolIdsPtr = MemoryAllocator.Alloc<int>(count).Ptr;
|
||||
}
|
||||
|
||||
GetComponentTypeIDsFor_Internal(entityID, poolIdsPtr, count);
|
||||
@ -1105,7 +1105,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
if (count >= BUFFER_THRESHOLD)
|
||||
{
|
||||
UnmanagedArrayUtility.Free(poolIdsPtr);
|
||||
MemoryAllocator.Free(poolIdsPtr);
|
||||
}
|
||||
}
|
||||
public ReadOnlySpan<object> GetComponentsFor(int entityID)
|
||||
|
||||
@ -5,7 +5,6 @@ using DCFApixels.DragonECS.Core;
|
||||
using DCFApixels.DragonECS.Core.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
@ -31,6 +30,10 @@ namespace DCFApixels.DragonECS
|
||||
private StructList<WorldComponentPoolAbstract> _worldComponentPools;
|
||||
private int _builtinWorldComponentsCount = 0;
|
||||
|
||||
public static int AllWorldsCount
|
||||
{
|
||||
get { return _worldIdDispenser.Count; }
|
||||
}
|
||||
static EcsWorld()
|
||||
{
|
||||
_worlds[NULL_WORLD_ID] = new NullWorld();
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#endif
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using static DCFApixels.DragonECS.Core.Internal.MemoryAllocator;
|
||||
#if ENABLE_IL2CPP
|
||||
using Unity.IL2CPP.CompilerServices;
|
||||
#endif
|
||||
@ -13,13 +14,13 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
[Il2CppSetOption(Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
#endif
|
||||
internal sealed class EcsWhereExecutor : MaskQueryExecutor
|
||||
internal sealed unsafe class EcsWhereExecutor : MaskQueryExecutor
|
||||
{
|
||||
private EcsMaskIterator _iterator;
|
||||
|
||||
private int[] _filteredAllEntities = new int[32];
|
||||
private HMem<int> _filteredAllEntities = Alloc<int>(32);
|
||||
private int _filteredAllEntitiesCount = 0;
|
||||
private int[] _filteredEntities = null;
|
||||
private HMem<int> _filteredEntities = default;
|
||||
private int _filteredEntitiesCount = 0;
|
||||
|
||||
private long _version;
|
||||
@ -54,6 +55,14 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
protected sealed override void OnDestroy()
|
||||
{
|
||||
if (_isDestroyed) { return; }
|
||||
if (_filteredAllEntities.IsCreated)
|
||||
{
|
||||
_filteredAllEntities.DisposeAndReset();
|
||||
}
|
||||
if (_filteredEntities.IsCreated)
|
||||
{
|
||||
_filteredEntities.DisposeAndReset();
|
||||
}
|
||||
_isDestroyed = true;
|
||||
_versionsChecker.Dispose();
|
||||
}
|
||||
@ -67,7 +76,7 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
if (_versionsChecker.CheckAndNext() == false)
|
||||
{
|
||||
_version++;
|
||||
_filteredAllEntitiesCount = _iterator.IterateTo(World.Entities, ref _filteredAllEntities);
|
||||
_filteredAllEntitiesCount = _iterator.CacheTo(World.Entities, ref _filteredAllEntities);
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@ -77,19 +86,19 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
if (span.IsNull) { Throw.ArgumentNull(nameof(span)); }
|
||||
if (span.WorldID != World.ID) { Throw.Quiery_ArgumentDifferentWorldsException(); }
|
||||
#endif
|
||||
if (_filteredEntities == null)
|
||||
if (_filteredEntities.IsCreated == false)
|
||||
{
|
||||
_filteredEntities = new int[32];
|
||||
_filteredEntities = Alloc<int>(32);
|
||||
}
|
||||
_filteredEntitiesCount = _iterator.IterateTo(span, ref _filteredEntities);
|
||||
_filteredEntitiesCount = _iterator.CacheTo(span, ref _filteredEntities);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public EcsSpan Execute()
|
||||
public EcsUnsafeSpan Execute()
|
||||
{
|
||||
Execute_Iternal();
|
||||
var result = new EcsUnsafeSpan(World.ID, _filteredAllEntities.Ptr, _filteredAllEntitiesCount);
|
||||
#if DEBUG && DRAGONECS_DEEP_DEBUG
|
||||
var newSpan = new EcsSpan(World.ID, _filteredAllEntities, _filteredAllEntitiesCount);
|
||||
using (EcsGroup group = EcsGroup.New(World))
|
||||
{
|
||||
foreach (var e in World.Entities)
|
||||
@ -100,29 +109,29 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
}
|
||||
}
|
||||
|
||||
if (group.SetEquals(newSpan) == false)
|
||||
if (group.SetEquals(result.ToSpan()) == false)
|
||||
{
|
||||
int[] array = new int[_filteredAllEntities.Length];
|
||||
var count = _iterator.IterateTo(World.Entities, ref array);
|
||||
var count = _iterator.CacheTo(World.Entities, ref array);
|
||||
|
||||
EcsDebug.PrintError(newSpan.ToString() + "\r\n" + group.ToSpan().ToString());
|
||||
EcsDebug.PrintError(result.ToString() + "\r\n" + group.ToSpan().ToString());
|
||||
Throw.DeepDebugException();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return new EcsSpan(World.ID, _filteredAllEntities, _filteredAllEntitiesCount);
|
||||
return result;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public EcsSpan ExecuteFor(EcsSpan span)
|
||||
public EcsUnsafeSpan ExecuteFor(EcsSpan span)
|
||||
{
|
||||
if (span.IsSourceEntities)
|
||||
{
|
||||
return Execute();
|
||||
}
|
||||
ExecuteFor_Iternal(span);
|
||||
var result = new EcsUnsafeSpan(World.ID, _filteredEntities.Ptr, _filteredEntitiesCount);
|
||||
#if DEBUG && DRAGONECS_DEEP_DEBUG
|
||||
var newSpan = new EcsSpan(World.ID, _filteredEntities, _filteredEntitiesCount);
|
||||
foreach (var e in newSpan)
|
||||
foreach (var e in result)
|
||||
{
|
||||
if (World.IsMatchesMask(Mask, e) == false)
|
||||
{
|
||||
@ -130,26 +139,28 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return new EcsSpan(World.ID, _filteredEntities, _filteredEntitiesCount);
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public EcsSpan Execute(Comparison<int> comparison)
|
||||
public EcsUnsafeSpan Execute(Comparison<int> comparison)
|
||||
{
|
||||
Execute_Iternal();
|
||||
ArraySortHalperX<int>.Sort(_filteredAllEntities, comparison, _filteredAllEntitiesCount);
|
||||
return new EcsSpan(World.ID, _filteredAllEntities, _filteredAllEntitiesCount);
|
||||
Span<int> result = _filteredAllEntities.AsSpan(_filteredAllEntitiesCount);
|
||||
result.Sort(comparison);
|
||||
return new EcsUnsafeSpan(World.ID, _filteredAllEntities.Ptr, _filteredAllEntitiesCount);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public EcsSpan ExecuteFor(EcsSpan span, Comparison<int> comparison)
|
||||
public EcsUnsafeSpan ExecuteFor(EcsSpan source, Comparison<int> comparison)
|
||||
{
|
||||
if (span.IsSourceEntities)
|
||||
if (source.IsSourceEntities)
|
||||
{
|
||||
return Execute(comparison);
|
||||
}
|
||||
ExecuteFor_Iternal(span);
|
||||
ArraySortHalperX<int>.Sort(_filteredEntities, comparison, _filteredEntitiesCount);
|
||||
return new EcsSpan(World.ID, _filteredEntities, _filteredEntitiesCount);
|
||||
ExecuteFor_Iternal(source);
|
||||
Span<int> result = _filteredEntities.AsSpan(_filteredEntitiesCount);
|
||||
result.Sort(comparison);
|
||||
return new EcsUnsafeSpan(World.ID, _filteredEntities.Ptr, _filteredEntitiesCount);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
if (_versionsChecker.CheckAndNext() == false)
|
||||
{
|
||||
_version++;
|
||||
_iterator.IterateTo(World.Entities, _filteredAllGroup);
|
||||
_iterator.CacheTo(World.Entities, _filteredAllGroup);
|
||||
#if DEBUG && DRAGONECS_DEEP_DEBUG
|
||||
if (_filteredGroup == null)
|
||||
{
|
||||
@ -98,7 +98,7 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
{
|
||||
_filteredGroup = EcsGroup.New(World);
|
||||
}
|
||||
_iterator.IterateTo(span, _filteredGroup);
|
||||
_iterator.CacheTo(span, _filteredGroup);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
||||
@ -84,6 +84,76 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region WhereUnsafe
|
||||
public static EcsUnsafeSpan WhereUnsafe<TCollection, TAspect>(this TCollection entities, out TAspect aspect)
|
||||
where TAspect : new()
|
||||
where TCollection : IEntityStorage
|
||||
{
|
||||
return entities.ToSpan().WhereUnsafe(out aspect);
|
||||
}
|
||||
public static EcsUnsafeSpan WhereUnsafe<TAspect>(this EcsReadonlyGroup group, out TAspect aspect)
|
||||
where TAspect : new()
|
||||
{
|
||||
return group.ToSpan().WhereUnsafe(out aspect);
|
||||
}
|
||||
public static EcsUnsafeSpan WhereUnsafe<TAspect>(this EcsSpan span, out TAspect aspect)
|
||||
where TAspect : new()
|
||||
{
|
||||
span.World.GetQueryCache(out EcsWhereExecutor executor, out aspect);
|
||||
return executor.ExecuteFor(span);
|
||||
}
|
||||
|
||||
public static EcsUnsafeSpan WhereUnsafe<TCollection>(this TCollection entities, IComponentMask mask)
|
||||
where TCollection : IEntityStorage
|
||||
{
|
||||
return entities.ToSpan().WhereUnsafe(mask);
|
||||
}
|
||||
public static EcsUnsafeSpan WhereUnsafe(this EcsReadonlyGroup group, IComponentMask mask)
|
||||
{
|
||||
return group.ToSpan().WhereUnsafe(mask);
|
||||
}
|
||||
public static EcsUnsafeSpan WhereUnsafe(this EcsSpan span, IComponentMask mask)
|
||||
{
|
||||
var executor = span.World.GetExecutorForMask<EcsWhereExecutor>(mask);
|
||||
return executor.ExecuteFor(span);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region WhereUnsafe with sort
|
||||
public static EcsUnsafeSpan WhereUnsafe<TCollection, TAspect>(this TCollection entities, out TAspect aspect, Comparison<int> comparison)
|
||||
where TAspect : new()
|
||||
where TCollection : IEntityStorage
|
||||
{
|
||||
return entities.ToSpan().WhereUnsafe(out aspect, comparison);
|
||||
}
|
||||
public static EcsUnsafeSpan WhereUnsafe<TAspect>(this EcsReadonlyGroup group, out TAspect aspect, Comparison<int> comparison)
|
||||
where TAspect : new()
|
||||
{
|
||||
return group.ToSpan().WhereUnsafe(out aspect, comparison);
|
||||
}
|
||||
public static EcsUnsafeSpan WhereUnsafe<TAspect>(this EcsSpan span, out TAspect aspect, Comparison<int> comparison)
|
||||
where TAspect : new()
|
||||
{
|
||||
span.World.GetQueryCache(out EcsWhereExecutor executor, out aspect);
|
||||
return executor.ExecuteFor(span, comparison);
|
||||
}
|
||||
|
||||
public static EcsUnsafeSpan WhereUnsafe<TCollection>(this TCollection entities, IComponentMask mask, Comparison<int> comparison)
|
||||
where TCollection : IEntityStorage
|
||||
{
|
||||
return entities.ToSpan().WhereUnsafe(mask, comparison);
|
||||
}
|
||||
public static EcsUnsafeSpan WhereUnsafe(this EcsReadonlyGroup group, IComponentMask mask, Comparison<int> comparison)
|
||||
{
|
||||
return group.ToSpan().WhereUnsafe(mask, comparison);
|
||||
}
|
||||
public static EcsUnsafeSpan WhereUnsafe(this EcsSpan span, IComponentMask mask, Comparison<int> comparison)
|
||||
{
|
||||
var executor = span.World.GetExecutorForMask<EcsWhereExecutor>(mask);
|
||||
return executor.ExecuteFor(span);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region WhereToGroup
|
||||
public static EcsReadonlyGroup WhereToGroup<TCollection, TAspect>(this TCollection entities, out TAspect aspect)
|
||||
where TAspect : new()
|
||||
|
||||
@ -1,25 +1,89 @@
|
||||
using System;
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using static DCFApixels.DragonECS.Core.Internal.MemoryAllocator;
|
||||
namespace DCFApixels.DragonECS.Core.Internal
|
||||
{
|
||||
internal static class AllocatorUtility
|
||||
internal static unsafe class AllocatorUtility
|
||||
{
|
||||
public static unsafe void ClearAllocatedMemory(IntPtr ptr, int startByte, int lengthInBytes)
|
||||
public static void ClearAllocatedMemory(IntPtr ptr, int startByte, int lengthInBytes)
|
||||
{
|
||||
ClearAllocatedMemory((byte*)ptr, startByte, lengthInBytes);
|
||||
}
|
||||
public static unsafe void ClearAllocatedMemory(byte* ptr, int startByte, int lengthInBytes)
|
||||
public static void ClearAllocatedMemory(byte* ptr, int startByte, int lengthInBytes)
|
||||
{
|
||||
#if ENABLE_DUMMY_SPAN
|
||||
lengthInBytes += startByte;
|
||||
for (int i = startByte; i < lengthInBytes; i++)
|
||||
{
|
||||
ptr[i] = 0;
|
||||
}
|
||||
#else
|
||||
Span<byte> memorySpan = new Span<byte>(ptr + startByte, lengthInBytes);
|
||||
memorySpan.Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int CacheTo(this EcsMaskIterator it, EcsSpan source, ref HMem<int> array)
|
||||
{
|
||||
switch (it.MaskFlags)
|
||||
{
|
||||
case EcsMaskFlags.Empty:
|
||||
{
|
||||
if(array.Length < source.Count)
|
||||
{
|
||||
array = Realloc<int>(array, source.Count);
|
||||
}
|
||||
source.AsSystemSpan().CopyTo(array.AsSpan());
|
||||
return source.Count;
|
||||
}
|
||||
case EcsMaskFlags.Inc:
|
||||
{
|
||||
return it.IterateOnlyInc(source).CacheTo(ref array);
|
||||
}
|
||||
case EcsMaskFlags.Exc:
|
||||
case EcsMaskFlags.Any:
|
||||
case EcsMaskFlags.IncExc:
|
||||
case EcsMaskFlags.IncAny:
|
||||
case EcsMaskFlags.ExcAny:
|
||||
case EcsMaskFlags.IncExcAny:
|
||||
{
|
||||
return it.Iterate(source).CacheTo(ref array);
|
||||
}
|
||||
case EcsMaskFlags.Broken:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Throw.UndefinedException();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int CacheTo(this EcsMaskIterator.OnlyIncEnumerable e, ref HMem<int> array)
|
||||
{
|
||||
int count = 0;
|
||||
var enumerator = e.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
if (array.Length <= count)
|
||||
{
|
||||
array = Realloc<int>(array, array.Length << 1);
|
||||
}
|
||||
array.Ptr[count++] = enumerator.Current;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int CacheTo(this EcsMaskIterator.Enumerable e, ref HMem<int> array)
|
||||
{
|
||||
int count = 0;
|
||||
var enumerator = e.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
if (array.Length <= count)
|
||||
{
|
||||
array = Realloc<int>(array, array.Length << 1);
|
||||
}
|
||||
array.Ptr[count++] = enumerator.Current;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#undef DEBUG
|
||||
#endif
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DCFApixels.DragonECS.Core.Internal
|
||||
@ -26,30 +27,30 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
}
|
||||
|
||||
#region AllocAndInit
|
||||
public static Handler AllocAndInit<T>(int count) where T : unmanaged
|
||||
public static HMem<T> AllocAndInit<T>(int count) where T : unmanaged
|
||||
{
|
||||
return AllocAndInit_Internal(Marshal.SizeOf<T>() * count, typeof(T));
|
||||
return new HMem<T>(AllocAndInit_Internal(Marshal.SizeOf<T>() * count, typeof(T)), count);
|
||||
}
|
||||
public static Handler AllocAndInit(int byteLength)
|
||||
public static HMem<byte> AllocAndInit(int byteLength)
|
||||
{
|
||||
return AllocAndInit_Internal(byteLength, null);
|
||||
return new HMem<byte>(AllocAndInit_Internal(byteLength, null), byteLength);
|
||||
}
|
||||
public static Handler AllocAndInit_Internal(int byteLength, Type type)
|
||||
{
|
||||
Handler handler = Alloc_Internal(byteLength, type);
|
||||
AllocatorUtility.ClearAllocatedMemory(handler.Ptr, 0, byteLength);
|
||||
AllocatorUtility.ClearAllocatedMemory(handler.RawPtr, 0, byteLength);
|
||||
return handler;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Alloc
|
||||
public static Handler Alloc<T>(int count) where T : unmanaged
|
||||
public static HMem<T> Alloc<T>(int count) where T : unmanaged
|
||||
{
|
||||
return Alloc_Internal(Marshal.SizeOf<T>() * count, typeof(T));
|
||||
return new HMem<T>(Alloc_Internal(Marshal.SizeOf<T>() * count, typeof(T)), count);
|
||||
}
|
||||
public static Handler Alloc(int byteLength)
|
||||
public static HMem<byte> Alloc(int byteLength)
|
||||
{
|
||||
return Alloc_Internal(byteLength, null);
|
||||
return new HMem<byte>(Alloc_Internal(byteLength, null), byteLength); ;
|
||||
}
|
||||
public static Handler Alloc_Internal(int byteLength, Type type)
|
||||
{
|
||||
@ -84,54 +85,78 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
#endregion
|
||||
|
||||
#region ReallocAndInit
|
||||
public static Handler ReallocAndInit<T>(void* target, int oldCount, int newCount) where T : unmanaged
|
||||
public static HMem<T> ReallocAndInit<T>(void* target, int oldCount, int newCount) where T : unmanaged
|
||||
{
|
||||
return ReallocAndInit<T>(Handler.FromDataPtr(target), oldCount, newCount);
|
||||
}
|
||||
public static Handler ReallocAndInit(void* target, int oldByteLength, int newByteLength)
|
||||
public static HMem<byte> ReallocAndInit(void* target, int oldByteLength, int newByteLength)
|
||||
{
|
||||
return ReallocAndInit(Handler.FromDataPtr(target), oldByteLength, newByteLength);
|
||||
}
|
||||
public static Handler ReallocAndInit<T>(Handler target, int oldCount, int newCount) where T : unmanaged
|
||||
public static HMem<T> ReallocAndInit<T>(HMem<T> target, int newCount) where T : unmanaged
|
||||
{
|
||||
var size = Marshal.SizeOf<T>();
|
||||
return ReallocAndInit_Internal(target, size * oldCount, size * newCount, typeof(T));
|
||||
return new HMem<T>(ReallocAndInit_Internal(target, size * target.Length, size * newCount, typeof(T)), newCount);
|
||||
}
|
||||
public static Handler ReallocAndInit(Handler target, int oldByteLength, int newByteLength)
|
||||
public static HMem<T> ReallocAndInit<T>(Handler target, int oldCount, int newCount) where T : unmanaged
|
||||
{
|
||||
return ReallocAndInit_Internal(target, oldByteLength, newByteLength, null);
|
||||
var size = Marshal.SizeOf<T>();
|
||||
return new HMem<T>(ReallocAndInit_Internal(target, size * oldCount, size * newCount, typeof(T)), newCount);
|
||||
}
|
||||
public static HMem<byte> ReallocAndInit(Handler target, int oldByteLength, int newByteLength)
|
||||
{
|
||||
return new HMem<byte>(ReallocAndInit_Internal(target, oldByteLength, newByteLength, null), newByteLength);
|
||||
}
|
||||
private static Handler ReallocAndInit_Internal(Handler target, int oldByteLength, int newByteLength, Type newType)
|
||||
{
|
||||
Handler handler = Realloc_Internal(target, newByteLength, newType);
|
||||
AllocatorUtility.ClearAllocatedMemory(handler.Ptr, oldByteLength, newByteLength - oldByteLength);
|
||||
AllocatorUtility.ClearAllocatedMemory(handler.RawPtr, oldByteLength, newByteLength - oldByteLength);
|
||||
return handler;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Realloc
|
||||
public static Handler Realloc<T>(void* target, int newCount) where T : unmanaged
|
||||
public static HMem<T> Realloc<T>(void* target, int newCount) where T : unmanaged
|
||||
{
|
||||
return Realloc<T>(Handler.FromDataPtr(target), Marshal.SizeOf<T>() * newCount);
|
||||
}
|
||||
public static Handler Realloc(void* target, int newByteLength)
|
||||
public static HMem<byte> Realloc(void* target, int newByteLength)
|
||||
{
|
||||
return Realloc(Handler.FromDataPtr(target), newByteLength);
|
||||
return new HMem<byte>(Realloc(Handler.FromDataPtr(target), newByteLength), newByteLength);
|
||||
}
|
||||
public static Handler Realloc<T>(Handler target, int newCount) where T : unmanaged
|
||||
public static HMem<T> Realloc<T>(Handler target, int newCount) where T : unmanaged
|
||||
{
|
||||
return Realloc_Internal(target, Marshal.SizeOf<T>() * newCount, typeof(T));
|
||||
return new HMem<T>(Realloc_Internal(target, Marshal.SizeOf<T>() * newCount, typeof(T)), newCount);
|
||||
}
|
||||
public static Handler Realloc(Handler target, int newByteLength)
|
||||
public static HMem<byte> Realloc(Handler target, int newByteLength)
|
||||
{
|
||||
return Realloc_Internal(target, newByteLength, null);
|
||||
return new HMem<byte>(Realloc_Internal(target, newByteLength, null), newByteLength);
|
||||
}
|
||||
private static Handler Realloc_Internal(Handler target, int newByteLength, Type newType)
|
||||
{
|
||||
newByteLength = newByteLength == 0 ? 1 : newByteLength;
|
||||
Meta* newHandledPtr = (Meta*)Marshal.ReAllocHGlobal((IntPtr)target.GetHandledPtr(), (IntPtr)newByteLength + sizeof(Meta));
|
||||
if (target.IsCreated == false)
|
||||
{
|
||||
return Alloc_Internal(newByteLength, newType);
|
||||
}
|
||||
#if DEBUG
|
||||
int id = 0;
|
||||
lock (_idDispenser)
|
||||
{
|
||||
if (_debugInfos.Length <= _idDispenser.Count)
|
||||
{
|
||||
Array.Resize(ref _debugInfos, ArrayUtility.NextPow2(_idDispenser.Count));
|
||||
}
|
||||
id = _idDispenser.UseFree();
|
||||
}
|
||||
#endif
|
||||
Meta* newHandledPtr = (Meta*)Marshal.ReAllocHGlobal(
|
||||
(IntPtr)target.GetHandledPtr(),
|
||||
(IntPtr)newByteLength + sizeof(Meta));
|
||||
Handler handler = Handler.FromHandledPtr(newHandledPtr);
|
||||
#if DEBUG
|
||||
newHandledPtr->ID = id;
|
||||
newHandledPtr->ByteLength = newByteLength;
|
||||
#if DRAGONECS_DEEP_DEBUG
|
||||
_debugInfos[newHandledPtr->ID].stackTrace = new System.Diagnostics.StackTrace();
|
||||
#endif
|
||||
@ -142,11 +167,39 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Clone
|
||||
public static HMem<T> From<T>(HMem<T> source)
|
||||
where T : unmanaged
|
||||
{
|
||||
var result = Alloc<T>(source.Length);
|
||||
source.AsSpan().CopyTo(result.AsSpan());
|
||||
return result;
|
||||
}
|
||||
public static HMem<T> From<T>(T* ptr, int length)
|
||||
where T : unmanaged
|
||||
{
|
||||
return From<T>(new ReadOnlySpan<T>(ptr, length));
|
||||
}
|
||||
public static HMem<T> From<T>(ReadOnlySpan<T> source)
|
||||
where T : unmanaged
|
||||
{
|
||||
var result = Alloc<T>(source.Length);
|
||||
source.CopyTo(result.AsSpan());
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Free
|
||||
public static void Free(Handler target)
|
||||
{
|
||||
Free_Internal(target.GetHandledPtr());
|
||||
}
|
||||
public static void FreeAndClear<T>(ref HMem<T> target)
|
||||
where T : unmanaged
|
||||
{
|
||||
Free_Internal(target.Handler.GetHandledPtr());
|
||||
target = default;
|
||||
}
|
||||
public static void FreeAndClear(ref Handler target)
|
||||
{
|
||||
Free_Internal(target.GetHandledPtr());
|
||||
@ -159,6 +212,10 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
private static void Free_Internal(Meta* handledPtr)
|
||||
{
|
||||
#if DEBUG
|
||||
if (handledPtr == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
lock (_idDispenser)
|
||||
{
|
||||
_idDispenser.Release(handledPtr->ID);
|
||||
@ -210,11 +267,90 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
}
|
||||
#endregion
|
||||
|
||||
public readonly struct HMem<T> : IDisposable, IEquatable<HMem<T>>
|
||||
where T : unmanaged
|
||||
{
|
||||
public readonly T* Ptr;
|
||||
public readonly int Length;
|
||||
|
||||
internal HMem(Handler handler, int length)
|
||||
{
|
||||
Ptr = handler.As<T>();
|
||||
Length = length;
|
||||
}
|
||||
|
||||
public bool IsCreated
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return Ptr != null; }
|
||||
}
|
||||
public IntPtr RawPtr
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return new IntPtr(Ptr); }
|
||||
}
|
||||
public Handler Handler
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return Handler.FromDataPtr(Ptr); }
|
||||
}
|
||||
|
||||
public HMem<U> As<U>()
|
||||
where U : unmanaged
|
||||
{
|
||||
if (IsCreated)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
long totalBytes = (long)Length * sizeof(T);
|
||||
long newLengthLong = totalBytes / sizeof(U);
|
||||
#if DEBUG
|
||||
if (totalBytes % sizeof(U) != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot cast Memory<{typeof(T).Name}> to Memory<{typeof(U).Name}> because the size of the underlying memory ({totalBytes} bytes) is not a multiple of the size of {typeof(U).Name} ({sizeof(U)} bytes).");
|
||||
}
|
||||
if (newLengthLong > int.MaxValue)
|
||||
{
|
||||
throw new InvalidOperationException($"Resulting length ({newLengthLong}) exceeds int.MaxValue.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return new HMem<U>(Handler, (int)newLengthLong);
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
Handler.Dispose();
|
||||
}
|
||||
|
||||
public override string ToString() { return Handler.DebuggerDisplay(); }
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override int GetHashCode() { return RawPtr.GetHashCode(); }
|
||||
public override bool Equals(object obj) { return obj is Handler h && h == this; }
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(HMem<T> other) { return other.Ptr == Ptr; }
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(HMem<T> a, HMem<T> b) { return a.Ptr == b.Ptr; }
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(HMem<T> a, HMem<T> b) { return a.Ptr != b.Ptr; }
|
||||
|
||||
public Span<T> AsSpan() { return new Span<T>(Ptr, Length); }
|
||||
public Span<T> AsSpan(int length)
|
||||
{
|
||||
#if DEBUG
|
||||
if (length > Length) { Throw.UndefinedException(); }
|
||||
#endif
|
||||
return new Span<T>(Ptr, length);
|
||||
}
|
||||
public static implicit operator Handler(HMem<T> memory) { return memory.Handler; }
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
[System.Diagnostics.DebuggerDisplay("{DebuggerDisplay()}")]
|
||||
[System.Diagnostics.DebuggerTypeProxy(typeof(DebuggerProxy))]
|
||||
#endif
|
||||
public readonly struct Handler : IDisposable
|
||||
public readonly struct Handler : IDisposable, IEquatable<Handler>
|
||||
{
|
||||
public static readonly Handler Empty = new Handler();
|
||||
internal readonly Meta* Data; // Data[-1] is meta;
|
||||
@ -239,16 +375,37 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
#endif
|
||||
}
|
||||
|
||||
public bool IsEmpty { get { return Data == null; } }
|
||||
public IntPtr Ptr { get { return (IntPtr)Data; } }
|
||||
public T* As<T>() where T : unmanaged { return (T*)Ptr; }
|
||||
public bool IsCreated
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return Data != null; }
|
||||
}
|
||||
public IntPtr RawPtr
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return (IntPtr)Data; }
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T* As<T>() where T : unmanaged { return (T*)RawPtr; }
|
||||
|
||||
void IDisposable.Dispose() { Free((void*)Ptr); }
|
||||
public void Dispose() { Free((void*)RawPtr); }
|
||||
|
||||
public override string ToString() { return DebuggerDisplay(); }
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override int GetHashCode() { return RawPtr.GetHashCode(); }
|
||||
public override bool Equals(object obj) { return obj is Handler h && h == this; }
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(Handler other) { return other.Data == Data; }
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(Handler a, Handler b) { return a.Data == b.Data; }
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(Handler a, Handler b) { return a.Data != b.Data; }
|
||||
|
||||
#region Debugger
|
||||
#if DEBUG
|
||||
#pragma warning disable IL3050 // Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.
|
||||
internal unsafe string DebuggerDisplay()
|
||||
internal string DebuggerDisplay()
|
||||
{
|
||||
if (Data == null)
|
||||
{
|
||||
@ -282,6 +439,7 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
private unsafe struct Union
|
||||
{
|
||||
@ -303,13 +461,13 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
|
||||
public HandlerDebugInfo[] OtherHandlersInfo;
|
||||
|
||||
public unsafe DebuggerProxy(Handler handler)
|
||||
public DebuggerProxy(Handler handler)
|
||||
{
|
||||
IsAlive = handler.Ptr.ToPointer() != null;
|
||||
IsAlive = handler.RawPtr.ToPointer() != null;
|
||||
if (IsAlive == false) { return; }
|
||||
|
||||
Meta = handler.GetHandledPtr()[0];
|
||||
_data = (byte*)handler.Ptr;
|
||||
_data = (byte*)handler.RawPtr;
|
||||
DebugInfo = _debugInfos[Meta.ID];
|
||||
|
||||
if (DebugInfo.type == null)
|
||||
@ -337,9 +495,15 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
|
||||
internal static class MemoryAllocatorHandlerExtensions
|
||||
{
|
||||
public static void Dispose(this ref MemoryAllocator.Handler self)
|
||||
public static void DisposeAndReset(this ref MemoryAllocator.Handler self)
|
||||
{
|
||||
MemoryAllocator.FreeAndClear(ref self);
|
||||
}
|
||||
public static void DisposeAndReset<T>(this ref MemoryAllocator.HMem<T> self)
|
||||
where T : unmanaged
|
||||
{
|
||||
self.Dispose();
|
||||
self = default;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -54,7 +54,7 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
{
|
||||
MemoryAllocator.Free(_ptr);
|
||||
}
|
||||
_ptr = MemoryAllocator.Alloc<byte>(byteSize).As<byte>();
|
||||
_ptr = MemoryAllocator.Alloc<byte>(byteSize).Ptr;
|
||||
_byteSize = byteSize;
|
||||
}
|
||||
return (T*)_ptr;
|
||||
|
||||
@ -6,7 +6,6 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DCFApixels.DragonECS.Core.Internal
|
||||
{
|
||||
@ -270,114 +269,6 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
|
||||
}
|
||||
}
|
||||
internal static unsafe class UnmanagedArrayUtility
|
||||
{
|
||||
private static class MetaCache<T>
|
||||
{
|
||||
public readonly static int Size;
|
||||
static MetaCache()
|
||||
{
|
||||
T def = default;
|
||||
Size = Marshal.SizeOf(def);
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T* New<T>(int capacity) where T : unmanaged
|
||||
{
|
||||
//Console.WriteLine($"{typeof(T).Name} - {Marshal.SizeOf<T>()} - {capacity} - {Marshal.SizeOf<T>() * capacity}");
|
||||
//return (T*)Marshal.AllocHGlobal(Marshal.SizeOf<T>() * capacity).ToPointer();
|
||||
return MemoryAllocator.Alloc<T>(capacity).As<T>();
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void New<T>(out T* ptr, int capacity) where T : unmanaged
|
||||
{
|
||||
//ptr = (T*)Marshal.AllocHGlobal(Marshal.SizeOf<T>() * capacity).ToPointer();
|
||||
ptr = MemoryAllocator.Alloc<T>(capacity).As<T>();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T* NewAndInit<T>(int capacity) where T : unmanaged
|
||||
{
|
||||
//int newSize = MetaCache<T>.Size * capacity;
|
||||
//byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
|
||||
//
|
||||
//for (int i = 0; i < newSize; i++)
|
||||
//{
|
||||
// *(newPointer + i) = 0;
|
||||
//}
|
||||
//
|
||||
//return (T*)newPointer;
|
||||
return MemoryAllocator.AllocAndInit<T>(capacity).As<T>();
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void NewAndInit<T>(out T* ptr, int capacity) where T : unmanaged
|
||||
{
|
||||
//int newSize = MetaCache<T>.Size * capacity;
|
||||
//byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
|
||||
//
|
||||
//for (int i = 0; i < newSize; i++)
|
||||
//{
|
||||
// *(newPointer + i) = 0;
|
||||
//}
|
||||
//
|
||||
//ptr = (T*)newPointer;
|
||||
ptr = MemoryAllocator.AllocAndInit<T>(capacity).As<T>();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Free(void* pointer)
|
||||
{
|
||||
//Marshal.FreeHGlobal(new IntPtr(pointer));
|
||||
MemoryAllocator.Free(dataPtr: pointer);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Free<T>(ref T* pointer, ref int length) where T : unmanaged
|
||||
{
|
||||
//Marshal.FreeHGlobal(new IntPtr(pointer));
|
||||
MemoryAllocator.Free(dataPtr: pointer);
|
||||
pointer = null;
|
||||
length = 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T* Clone<T>(T* sourcePtr, int length) where T : unmanaged
|
||||
{
|
||||
T* clone = New<T>(length);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
clone[i] = sourcePtr[i];
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T* Resize<T>(void* oldPointer, int newCount) where T : unmanaged
|
||||
{
|
||||
//return (T*)(Marshal.ReAllocHGlobal(
|
||||
// new IntPtr(oldPointer),
|
||||
// new IntPtr(MetaCache<T>.Size * newCount))).ToPointer();
|
||||
return MemoryAllocator.Realloc<T>(MemoryAllocator.Handler.FromDataPtr(oldPointer), newCount).As<T>();
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T* ResizeAndInit<T>(void* oldPointer, int oldSize, int newSize) where T : unmanaged
|
||||
{
|
||||
//int sizeT = MetaCache<T>.Size;
|
||||
//T* result = (T*)Marshal.ReAllocHGlobal(
|
||||
// new IntPtr(oldPointer),
|
||||
// new IntPtr(sizeT * newSize)).ToPointer();
|
||||
//Init((byte*)result, sizeT * oldSize, sizeT * newSize);
|
||||
//return result;
|
||||
return MemoryAllocator.ReallocAndInit<T>(MemoryAllocator.Handler.FromDataPtr(oldPointer), oldSize, newSize).As<T>();
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void Init(byte* pointer, int startByteIndex, int endByteIndex)
|
||||
{
|
||||
for (int i = startByteIndex; i < endByteIndex; i++)
|
||||
{
|
||||
*(pointer + i) = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class CollectionUtility
|
||||
{
|
||||
@ -390,4 +281,24 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
return $"{name}({range.Count()}) {{{string.Join(", ", range.Select(o => o.ToString()))}}})";
|
||||
}
|
||||
}
|
||||
|
||||
internal static class SpanUtility
|
||||
{
|
||||
public static void Sort<T>(Span<T> span, Comparison<T> comparison)
|
||||
{
|
||||
span.Sort(new StructComparison<T>(comparison));
|
||||
}
|
||||
private readonly struct StructComparison<T> : IComparer<T>
|
||||
{
|
||||
public readonly Comparison<T> Comparison;
|
||||
public StructComparison(Comparison<T> comparison)
|
||||
{
|
||||
Comparison = comparison;
|
||||
}
|
||||
public int Compare(T x, T y)
|
||||
{
|
||||
return Comparison(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -38,13 +38,13 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public UnsafeArray(int length)
|
||||
{
|
||||
UnmanagedArrayUtility.New(out ptr, length);
|
||||
ptr = MemoryAllocator.Alloc<T>(length).Ptr;
|
||||
Length = length;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public UnsafeArray(int length, bool isInit)
|
||||
{
|
||||
UnmanagedArrayUtility.NewAndInit(out ptr, length);
|
||||
ptr = MemoryAllocator.AllocAndInit<T>(length).Ptr;
|
||||
Length = length;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@ -90,18 +90,20 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public UnsafeArray<T> Clone()
|
||||
{
|
||||
return new UnsafeArray<T>(UnmanagedArrayUtility.Clone(ptr, Length), Length);
|
||||
return new UnsafeArray<T>(MemoryAllocator.From(ptr, Length).Ptr, Length);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Dispose()
|
||||
{
|
||||
UnmanagedArrayUtility.Free(ref ptr, ref Length);
|
||||
MemoryAllocator.Free(ptr);
|
||||
ptr = default;
|
||||
Length = default;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadonlyDispose()
|
||||
{
|
||||
UnmanagedArrayUtility.Free(ptr);
|
||||
MemoryAllocator.Free(ptr);
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
@ -114,6 +116,9 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
return CollectionUtility.AutoToString(elements, "ua");
|
||||
}
|
||||
|
||||
public Span<T> AsSpan() { return new Span<T>(ptr, Length); }
|
||||
public T[] ToArray() { return AsSpan().ToArray(); }
|
||||
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); }
|
||||
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
||||
@ -1,202 +0,0 @@
|
||||
#if ENABLE_DUMMY_SPAN
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
|
||||
using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
internal static class ThrowHelper
|
||||
{
|
||||
public static void ThrowIndexOutOfRangeException() => throw new IndexOutOfRangeException();
|
||||
public static void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException();
|
||||
public static void ThrowInvalidOperationException() => throw new InvalidOperationException();
|
||||
}
|
||||
[DebuggerDisplay("{ToString(),raw}")]
|
||||
public readonly ref struct ReadOnlySpan<T>
|
||||
{
|
||||
public static ReadOnlySpan<T> Empty => new ReadOnlySpan<T>(null);
|
||||
|
||||
internal readonly T[] _array;
|
||||
private readonly int _start;
|
||||
private readonly int _length;
|
||||
|
||||
#region Properties
|
||||
public int Length => _length;
|
||||
public bool IsEmpty => _length == 0;
|
||||
public ref readonly T this[int index]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
if ((uint)index >= (uint)_length || (uint)index < 0)
|
||||
ThrowHelper.ThrowIndexOutOfRangeException();
|
||||
return ref _array[index + _start];
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ReadOnlySpan(T[] array)
|
||||
{
|
||||
_array = array ?? Array.Empty<T>();
|
||||
_start = 0;
|
||||
_length = array.Length;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ReadOnlySpan(T[] array, int start, int length)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
if (start != 0 || length != 0)
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException();
|
||||
_array = Array.Empty<T>();
|
||||
_start = 0;
|
||||
_length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException();
|
||||
|
||||
_array = array;
|
||||
_start = start;
|
||||
_length = length;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Object
|
||||
#pragma warning disable CS0809 // Óñòàðåâøèé ÷ëåí ïåðåîïðåäåëÿåò íåóñòàðåâøèé ÷ëåí
|
||||
[Obsolete("Equals() on ReadOnlySpan will always throw an exception. Use the equality operator instead.")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public override bool Equals(object obj) => throw new NotSupportedException();
|
||||
[Obsolete("GetHashCode() on ReadOnlySpan will always throw an exception.")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public override int GetHashCode() => throw new NotSupportedException();
|
||||
#pragma warning restore CS0809 // Óñòàðåâøèé ÷ëåí ïåðåîïðåäåëÿåò íåóñòàðåâøèé ÷ëåí
|
||||
public override string ToString()
|
||||
{
|
||||
//if (typeof(T) == typeof(char))
|
||||
// return new string(new ReadOnlySpan<char>(ref Unsafe.As<T, char>(ref _reference), _length));
|
||||
return $"System.ReadOnlySpan<{typeof(T).Name}>[{_length}]";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region operators
|
||||
public static bool operator !=(ReadOnlySpan<T> left, ReadOnlySpan<T> right) => !(left == right);
|
||||
|
||||
public static implicit operator ReadOnlySpan<T>(T[] array) => new ReadOnlySpan<T>(array);
|
||||
|
||||
public static implicit operator ReadOnlySpan<T>(ArraySegment<T> segment) => new ReadOnlySpan<T>(segment.Array, segment.Offset, segment.Count);
|
||||
public static bool operator ==(ReadOnlySpan<T> left, ReadOnlySpan<T> right) => left._length == right._length && left._array == right._array;
|
||||
#endregion
|
||||
|
||||
#region Enumerator
|
||||
public Enumerator GetEnumerator() => new Enumerator(this);
|
||||
public ref struct Enumerator
|
||||
{
|
||||
private readonly ReadOnlySpan<T> _span;
|
||||
private int _index;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal Enumerator(ReadOnlySpan<T> span)
|
||||
{
|
||||
_span = span;
|
||||
_index = span._start - 1;
|
||||
}
|
||||
public ref readonly T Current
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => ref _span[_index];
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool MoveNext()
|
||||
{
|
||||
int index = _index + 1;
|
||||
if (index < _span.Length)
|
||||
{
|
||||
_index = index;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public ref readonly T GetPinnableReference()
|
||||
{
|
||||
if (_length != 0) ThrowHelper.ThrowInvalidOperationException();
|
||||
return ref _array[0];
|
||||
}
|
||||
|
||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
//public void CopyTo(Span<T> destination)
|
||||
//{
|
||||
// if ((uint)_length <= (uint)destination.Length)
|
||||
// {
|
||||
// Buffer.Memmove(ref destination._reference, ref _reference, (uint)_length);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ThrowHelper.ThrowArgumentException_DestinationTooShort();
|
||||
// }
|
||||
//}
|
||||
|
||||
//public bool TryCopyTo(Span<T> destination)
|
||||
//{
|
||||
// bool retVal = false;
|
||||
// if ((uint)_length <= (uint)destination.Length)
|
||||
// {
|
||||
// Buffer.Memmove(ref destination._reference, ref _reference, (uint)_length);
|
||||
// retVal = true;
|
||||
// }
|
||||
// return retVal;
|
||||
//}
|
||||
public void CopyTo(T[] array)
|
||||
{
|
||||
if (_length > array.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
for (int i = 0; i < _length; i++)
|
||||
{
|
||||
array[i] = _array[i];
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ReadOnlySpan<T> Slice(int start)
|
||||
{
|
||||
if ((uint)start > (uint)_length)
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException();
|
||||
|
||||
return new ReadOnlySpan<T>(_array, _start + start, _length - start);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ReadOnlySpan<T> Slice(int start, int length)
|
||||
{
|
||||
if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException();
|
||||
|
||||
return new ReadOnlySpan<T>(_array, _start + start, length);
|
||||
}
|
||||
|
||||
public T[] ToArray()
|
||||
{
|
||||
if (_length == 0)
|
||||
return Array.Empty<T>();
|
||||
var result = new T[_length];
|
||||
Array.Copy(_array, _start, result, 0, _length);
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -62,6 +62,14 @@ namespace DCFApixels.DragonECS.Core.Unchecked
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Unsafe Span
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe EcsUnsafeSpan CreateUnsafeSpan(short worldID, int* ptr, int length)
|
||||
{
|
||||
return new EcsUnsafeSpan(worldID, ptr, length);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EcsGroup
|
||||
public static EcsGroup GetSourceInstance(EcsReadonlyGroup group)
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user