diff --git a/Svelto.Common b/Svelto.Common index 656980d..ec2fd73 160000 --- a/Svelto.Common +++ b/Svelto.Common @@ -1 +1 @@ -Subproject commit 656980d4e1026955f27e84f97b77339fd7cbd87c +Subproject commit ec2fd735014e3c54889dbad2a542515626d73a7f diff --git a/Svelto.ECS/Core/EntityReference/EnginesRoot.LocatorMap.cs b/Svelto.ECS/Core/EntityReference/EnginesRoot.LocatorMap.cs index 147d53c..69dca5d 100644 --- a/Svelto.ECS/Core/EntityReference/EnginesRoot.LocatorMap.cs +++ b/Svelto.ECS/Core/EntityReference/EnginesRoot.LocatorMap.cs @@ -222,6 +222,7 @@ namespace Svelto.ECS } internal LocatorMap entityLocator => _entityLocator; + LocatorMap _entityLocator; } } \ No newline at end of file diff --git a/Svelto.ECS/Core/GroupHashMap.cs b/Svelto.ECS/Core/GroupHashMap.cs index 8e761d9..6702aae 100644 --- a/Svelto.ECS/Core/GroupHashMap.cs +++ b/Svelto.ECS/Core/GroupHashMap.cs @@ -77,7 +77,7 @@ namespace Svelto.ECS if(_groupsByHash.ContainsKey(nameHash)) throw new ECSException($"Group hash collision with {name} and {_groupsByHash[nameHash]}"); - Console.LogDebug($"Reigstering group {name} with ID {(uint)exclusiveGroupStruct} to {nameHash}"); + Console.LogDebug($"Registering group {name} with ID {(uint)exclusiveGroupStruct} to {nameHash}"); _groupsByHash.Add(nameHash, exclusiveGroupStruct); _hashByGroups.Add(exclusiveGroupStruct, nameHash); diff --git a/Svelto.ECS/Core/Groups/ExclusiveGroup.cs b/Svelto.ECS/Core/Groups/ExclusiveGroup.cs index b931d0e..2047525 100644 --- a/Svelto.ECS/Core/Groups/ExclusiveGroup.cs +++ b/Svelto.ECS/Core/Groups/ExclusiveGroup.cs @@ -18,20 +18,19 @@ namespace Svelto.ECS /// public static ExclusiveGroup[] GroupOfGroups = { MyExclusiveGroup1, ...}; //for each on this! /// } /// - ///To debug it use in your debug window: Svelto.ECS.Debugger.EGID.GetGroupNameFromId(groupID) public sealed class ExclusiveGroup { - public const uint MaxNumberOfExclusiveGroups = 2 << 20; + public const uint MaxNumberOfExclusiveGroups = 2 << 20; public ExclusiveGroup(ExclusiveGroupBitmask bitmask = 0) { - _group = ExclusiveGroupStruct.Generate((byte)bitmask); + _group = ExclusiveGroupStruct.Generate((byte) bitmask); } public ExclusiveGroup(string recognizeAs, ExclusiveGroupBitmask bitmask = 0) { - _group = ExclusiveGroupStruct.Generate((byte)bitmask); + _group = ExclusiveGroupStruct.Generate((byte) bitmask); _knownGroups.Add(recognizeAs, _group); } @@ -66,13 +65,13 @@ namespace Svelto.ECS return (uint) @group._group; } - public static ExclusiveGroupStruct operator+(ExclusiveGroup a, uint b) + public static ExclusiveGroupStruct operator +(ExclusiveGroup a, uint b) { #if DEBUG if (a._range == 0) - throw new ECSException($"Adding values to a not ranged ExclusiveGroup: {(uint)a}"); + throw new ECSException($"Adding values to a not ranged ExclusiveGroup: {(uint) a}"); if (b >= a._range) - throw new ECSException($"Using out of range group: {(uint)a} + {b}"); + throw new ECSException($"Using out of range group: {(uint) a} + {b}"); #endif return a._group + b; } @@ -91,12 +90,12 @@ namespace Svelto.ECS return _group.ToString(); } - static readonly Dictionary _knownGroups = new Dictionary(); + static readonly Dictionary _knownGroups = + new Dictionary(); #if DEBUG readonly ushort _range; #endif ExclusiveGroupStruct _group; } -} +} \ No newline at end of file diff --git a/Svelto.ECS/Core/Groups/ExclusiveGroupStruct.cs b/Svelto.ECS/Core/Groups/ExclusiveGroupStruct.cs index bd24981..e38290e 100644 --- a/Svelto.ECS/Core/Groups/ExclusiveGroupStruct.cs +++ b/Svelto.ECS/Core/Groups/ExclusiveGroupStruct.cs @@ -122,6 +122,8 @@ namespace Svelto.ECS internal ExclusiveGroupStruct(uint groupID):this() { + DBC.ECS.Check.Require(groupID < 0xFFFFFF); + _id = groupID; } diff --git a/Svelto.ECS/Core/Groups/GroupCompound.cs b/Svelto.ECS/Core/Groups/GroupCompound.cs index 8ae5530..3a29e63 100644 --- a/Svelto.ECS/Core/Groups/GroupCompound.cs +++ b/Svelto.ECS/Core/Groups/GroupCompound.cs @@ -5,6 +5,19 @@ using Svelto.DataStructures; namespace Svelto.ECS { + /// + /// This mechanism is not for thread-safety but to be sure that all the permutations of group tags always + /// point to the same group ID. + /// A group compound can generate several permutation of tags, so that the order of the tag doesn't matter, + /// but for this to work, each permutation must be identified by the same ID (generated by the unique combination) + /// + static class GroupCompoundInitializer + { + internal static readonly ThreadLocal skipStaticCompoundConstructorsWith4Tags = new ThreadLocal(); + internal static readonly ThreadLocal skipStaticCompoundConstructorsWith3Tags = new ThreadLocal(); + internal static readonly ThreadLocal skipStaticCompoundConstructorsWith2Tags = new ThreadLocal(); + } + public abstract class GroupCompound where G1 : GroupTag where G2 : GroupTag where G3 : GroupTag @@ -22,41 +35,28 @@ namespace Svelto.ECS static GroupCompound() { - if (Interlocked.CompareExchange(ref isInitializing, 1, 0) == 0) + //avoid race conditions if compounds are using on multiple thread + if (Interlocked.CompareExchange(ref isInitializing, 1, 0) == 0 + && GroupCompoundInitializer.skipStaticCompoundConstructorsWith4Tags.Value == false) { _Groups = new FasterList(1); - var Group = new ExclusiveGroup(); - _Groups.Add(Group); - _GroupsHashSet = new HashSet(_Groups.ToArrayFast(out _)); - - GroupCompound.Add(Group); - GroupCompound.Add(Group); - GroupCompound.Add(Group); - GroupCompound.Add(Group); - - GroupCompound.Add(Group); // and must share the same array - GroupCompound.Add(Group); - GroupCompound.Add(Group); - GroupCompound.Add(Group); - GroupCompound.Add(Group); - GroupCompound.Add(Group); - - //This is done here to be sure that the group is added once per group tag - //(if done inside the previous group compound it would be added multiple times) - GroupTag.Add(Group); - GroupTag.Add(Group); - GroupTag.Add(Group); - GroupTag.Add(Group); - + var group = new ExclusiveGroup(); + _Groups.Add(group); + + var name = + $"Compound: {typeof(G1).Name}-{typeof(G2).Name}-{typeof(G3).Name}-{typeof(G4).Name} ID {(uint) group}"; #if DEBUG - GroupNamesMap.idToName[(uint) Group] = - $"Compound: {typeof(G1).Name}-{typeof(G2).Name}-{typeof(G3).Name}-{typeof(G4).Name} ID {(uint) Group}"; + GroupNamesMap.idToName[(uint) group] = name; #endif - GroupHashMap.RegisterGroup(BuildGroup, - $"Compound: {typeof(G1).Name}-{typeof(G2).Name}-{typeof(G3).Name}-{typeof(G4).Name}"); + GroupHashMap.RegisterGroup(group, name); + + _GroupsHashSet = new HashSet(_Groups.ToArrayFast(out _)); - //all the combinations must share the same group and group hashset + GroupCompoundInitializer.skipStaticCompoundConstructorsWith4Tags.Value = true; + + //all the permutations must share the same group and group hashset. Warm them up, avoid call the + //constructors again, set the desired value GroupCompound._Groups = _Groups; GroupCompound._Groups = _Groups; GroupCompound._Groups = _Groups; @@ -80,6 +80,9 @@ namespace Svelto.ECS GroupCompound._Groups = _Groups; GroupCompound._Groups = _Groups; GroupCompound._Groups = _Groups; + + //all the permutations are warmed up now + GroupCompoundInitializer.skipStaticCompoundConstructorsWith4Tags.Value = false; GroupCompound._GroupsHashSet = _GroupsHashSet; GroupCompound._GroupsHashSet = _GroupsHashSet; @@ -104,6 +107,25 @@ namespace Svelto.ECS GroupCompound._GroupsHashSet = _GroupsHashSet; GroupCompound._GroupsHashSet = _GroupsHashSet; GroupCompound._GroupsHashSet = _GroupsHashSet; + + GroupCompound.Add(group); + GroupCompound.Add(group); + GroupCompound.Add(group); + GroupCompound.Add(group); + + GroupCompound.Add(group); // and must share the same array + GroupCompound.Add(group); + GroupCompound.Add(group); + GroupCompound.Add(group); + GroupCompound.Add(group); + GroupCompound.Add(group); + + //This is done here to be sure that the group is added once per group tag + //(if done inside the previous group compound it would be added multiple times) + GroupTag.Add(group); + GroupTag.Add(group); + GroupTag.Add(group); + GroupTag.Add(group); } } @@ -117,7 +139,10 @@ namespace Svelto.ECS _GroupsHashSet.Add(group); } - public static bool Includes(ExclusiveGroupStruct @group) { return _GroupsHashSet.Contains(@group); } + public static bool Includes(ExclusiveGroupStruct @group) + { + return _GroupsHashSet.Contains(@group); + } } public abstract class GroupCompound @@ -130,7 +155,7 @@ namespace Svelto.ECS new FasterReadOnlyList(_Groups); public static ExclusiveBuildGroup BuildGroup => new ExclusiveBuildGroup(_Groups[0]); - + static int isInitializing; internal static void Add(ExclusiveGroupStruct group) @@ -143,35 +168,31 @@ namespace Svelto.ECS _GroupsHashSet.Add(group); } - public static bool Includes(ExclusiveGroupStruct @group) { return _GroupsHashSet.Contains(@group); } + public static bool Includes(ExclusiveGroupStruct @group) + { + return _GroupsHashSet.Contains(@group); + } static GroupCompound() { - if (Interlocked.CompareExchange(ref isInitializing, 1, 0) == 0) + if (Interlocked.CompareExchange(ref isInitializing, 1, 0) == 0 && + GroupCompoundInitializer.skipStaticCompoundConstructorsWith3Tags.Value == false) { _Groups = new FasterList(1); - var Group = new ExclusiveGroup(); - _Groups.Add(Group); - _GroupsHashSet = new HashSet(_Groups.ToArrayFast(out _)); - - GroupCompound.Add(Group); // and must share the same array - GroupCompound.Add(Group); - GroupCompound.Add(Group); - - //This is done here to be sure that the group is added once per group tag - //(if done inside the previous group compound it would be added multiple times) - GroupTag.Add(Group); - GroupTag.Add(Group); - GroupTag.Add(Group); + var group = new ExclusiveGroup(); + _Groups.Add(group); + var name = $"Compound: {typeof(G1).Name}-{typeof(G2).Name}-{typeof(G3).Name} ID {(uint) group}"; #if DEBUG - GroupNamesMap.idToName[(uint) Group] = - $"Compound: {typeof(G1).Name}-{typeof(G2).Name}-{typeof(G3).Name} ID {(uint) Group}"; + GroupNamesMap.idToName[(uint) group] = name; #endif - GroupHashMap.RegisterGroup(BuildGroup, - $"Compound: {typeof(G1).Name}-{typeof(G2).Name}-{typeof(G3).Name}"); + GroupHashMap.RegisterGroup(group, name); + _GroupsHashSet = new HashSet(_Groups.ToArrayFast(out _)); + + GroupCompoundInitializer.skipStaticCompoundConstructorsWith3Tags.Value = true; + //all the combinations must share the same group and group hashset GroupCompound._Groups = _Groups; GroupCompound._Groups = _Groups; @@ -179,11 +200,24 @@ namespace Svelto.ECS GroupCompound._Groups = _Groups; GroupCompound._Groups = _Groups; + //all the constructor have been called now + GroupCompoundInitializer.skipStaticCompoundConstructorsWith3Tags.Value = false; + GroupCompound._GroupsHashSet = _GroupsHashSet; GroupCompound._GroupsHashSet = _GroupsHashSet; GroupCompound._GroupsHashSet = _GroupsHashSet; GroupCompound._GroupsHashSet = _GroupsHashSet; GroupCompound._GroupsHashSet = _GroupsHashSet; + + GroupCompound.Add(group); // and must share the same array + GroupCompound.Add(group); + GroupCompound.Add(group); + + //This is done here to be sure that the group is added once per group tag + //(if done inside the previous group compound it would be added multiple times) + GroupTag.Add(group); + GroupTag.Add(group); + GroupTag.Add(group); } } } @@ -197,7 +231,7 @@ namespace Svelto.ECS new FasterReadOnlyList(_Groups); public static ExclusiveBuildGroup BuildGroup => new ExclusiveBuildGroup(_Groups[0]); - + static int isInitializing; internal static void Add(ExclusiveGroupStruct group) @@ -210,30 +244,37 @@ namespace Svelto.ECS _GroupsHashSet.Add(group); } - public static bool Includes(ExclusiveGroupStruct @group) { return _GroupsHashSet.Contains(@group); } + public static bool Includes(ExclusiveGroupStruct @group) + { + return _GroupsHashSet.Contains(@group); + } static GroupCompound() { - if (Interlocked.CompareExchange(ref isInitializing, 1, 0) == 0) + if (Interlocked.CompareExchange(ref isInitializing, 1, 0) == 0 && + GroupCompoundInitializer.skipStaticCompoundConstructorsWith2Tags.Value == false) { - var Group = new ExclusiveGroup(); + var group = new ExclusiveGroup(); _Groups = new FasterList(1); - _Groups.Add(Group); - _GroupsHashSet = new HashSet(_Groups.ToArrayFast(out _)); - - //every abstract group preemptively adds this group, it may or may not be empty in future - GroupTag.Add(Group); - GroupTag.Add(Group); + _Groups.Add(group); + var groupName = $"Compound: {typeof(G1).Name}-{typeof(G2).Name} ID {(uint) group}"; #if DEBUG - GroupNamesMap.idToName[(uint) Group] = $"Compound: {typeof(G1).Name}-{typeof(G2).Name} ID {(uint) Group}"; + GroupNamesMap.idToName[(uint) group] = groupName; #endif - GroupHashMap.RegisterGroup(BuildGroup, - $"Compound: {typeof(G1).Name}-{typeof(G2).Name}"); + GroupHashMap.RegisterGroup(group, groupName); + + _GroupsHashSet = new HashSet(_Groups.ToArrayFast(out _)); - GroupCompound._Groups = _Groups; - GroupCompound._GroupsHashSet = _GroupsHashSet; + GroupCompoundInitializer.skipStaticCompoundConstructorsWith2Tags.Value = true; + GroupCompound._Groups = _Groups; + GroupCompoundInitializer.skipStaticCompoundConstructorsWith2Tags.Value = false; + GroupCompound._GroupsHashSet = _GroupsHashSet; + + //every abstract group preemptively adds this group, it may or may not be empty in future + GroupTag.Add(group); + GroupTag.Add(group); } } } @@ -254,7 +295,7 @@ namespace Svelto.ECS new FasterReadOnlyList(_Groups); public static ExclusiveBuildGroup BuildGroup => new ExclusiveBuildGroup(_Groups[0]); - + static int isInitializing; static GroupTag() @@ -263,19 +304,22 @@ namespace Svelto.ECS { var group = new ExclusiveGroup(); _Groups.Add(group); - _GroupsHashSet = new HashSet(_Groups.ToArrayFast(out _)); + -#if DEBUG var typeInfo = typeof(T); + + var name = $"Compound: {typeInfo.Name} ID {(uint) @group}"; +#if DEBUG var typeInfoBaseType = typeInfo.BaseType; if (typeInfoBaseType.GenericTypeArguments[0] != typeInfo) throw new ECSException("Invalid Group Tag declared"); - - GroupNamesMap.idToName[(uint)group] = $"Compound: {typeInfo.Name} ID {(uint)group}"; + + GroupNamesMap.idToName[(uint) group] = name; #endif - GroupHashMap.RegisterGroup(BuildGroup, - $"Compound: {typeof(T).FullName}"); - } + GroupHashMap.RegisterGroup(group, name); + + _GroupsHashSet = new HashSet(_Groups.ToArrayFast(out _)); + } } //Each time a new combination of group tags is found a new group is added. @@ -289,6 +333,9 @@ namespace Svelto.ECS _GroupsHashSet.Add(group); } - public static bool Includes(ExclusiveGroupStruct @group) { return _GroupsHashSet.Contains(@group); } + public static bool Includes(ExclusiveGroupStruct @group) + { + return _GroupsHashSet.Contains(@group); + } } } \ No newline at end of file diff --git a/Svelto.ECS/Core/Hybrid/ValueReference.cs b/Svelto.ECS/Core/Hybrid/ValueReference.cs index ed5a9ac..c11990f 100644 --- a/Svelto.ECS/Core/Hybrid/ValueReference.cs +++ b/Svelto.ECS/Core/Hybrid/ValueReference.cs @@ -21,7 +21,7 @@ namespace Svelto.ECS.Hybrid public ValueReference(T obj) { _pointer = GCHandle.Alloc(obj, GCHandleType.Normal); } - public W Convert(W implementer) where W:T, new() + public W Convert(W implementer) where W:T { var pointerTarget = _pointer.Target; return (W)pointerTarget; diff --git a/Svelto.ECS/DataStructures/Unmanaged/AtomicNativeBags.cs b/Svelto.ECS/DataStructures/Unmanaged/AtomicNativeBags.cs index f7ce630..ee80a65 100644 --- a/Svelto.ECS/DataStructures/Unmanaged/AtomicNativeBags.cs +++ b/Svelto.ECS/DataStructures/Unmanaged/AtomicNativeBags.cs @@ -72,7 +72,7 @@ namespace Svelto.ECS.DataStructures } } -#if UNITY_COLLECTIONS +#if UNITY_COLLECTIONS || UNITY_JOBS || UNITY_BURST [global::Unity.Collections.LowLevel.Unsafe.NativeDisableUnsafePtrRestriction] #endif NativeBag* _data; diff --git a/Svelto.ECS/DataStructures/Unmanaged/NativeBag.cs b/Svelto.ECS/DataStructures/Unmanaged/NativeBag.cs index e2252fe..16478a4 100644 --- a/Svelto.ECS/DataStructures/Unmanaged/NativeBag.cs +++ b/Svelto.ECS/DataStructures/Unmanaged/NativeBag.cs @@ -273,7 +273,7 @@ namespace Svelto.ECS.DataStructures #if ENABLE_THREAD_SAFE_CHECKS int _threadSentinel; #endif -#if UNITY_COLLECTIONS +#if UNITY_COLLECTIONS || UNITY_JOBS || UNITY_BURST [global::Unity.Collections.LowLevel.Unsafe.NativeDisableUnsafePtrRestriction] #endif unsafe UnsafeBlob* _queue; diff --git a/Svelto.ECS/DataStructures/Unmanaged/NativeDynamicArray.cs b/Svelto.ECS/DataStructures/Unmanaged/NativeDynamicArray.cs index dd05cc7..b92dfec 100644 --- a/Svelto.ECS/DataStructures/Unmanaged/NativeDynamicArray.cs +++ b/Svelto.ECS/DataStructures/Unmanaged/NativeDynamicArray.cs @@ -377,7 +377,7 @@ namespace Svelto.ECS.DataStructures } } -#if UNITY_COLLECTIONS +#if UNITY_COLLECTIONS || UNITY_JOBS || UNITY_BURST [global::Unity.Burst.NoAlias] [global::Unity.Collections.LowLevel.Unsafe.NativeDisableUnsafePtrRestriction] #endif unsafe UnsafeArray* _list; diff --git a/Svelto.ECS/DataStructures/Unmanaged/SharedNativeInt.cs b/Svelto.ECS/DataStructures/Unmanaged/SharedNativeInt.cs index 60d82da..f5f9698 100644 --- a/Svelto.ECS/DataStructures/Unmanaged/SharedNativeInt.cs +++ b/Svelto.ECS/DataStructures/Unmanaged/SharedNativeInt.cs @@ -6,7 +6,7 @@ namespace Svelto.ECS.DataStructures { public struct SharedNativeInt: IDisposable { -#if UNITY_COLLECTIONS +#if UNITY_COLLECTIONS || UNITY_JOBS || UNITY_BURST [global::Unity.Collections.LowLevel.Unsafe.NativeDisableUnsafePtrRestriction] #endif unsafe int* data; diff --git a/Svelto.ECS/DataStructures/Unmanaged/ThreadSafeNativeBag.cs b/Svelto.ECS/DataStructures/Unmanaged/ThreadSafeNativeBag.cs index d5d7187..003f07c 100644 --- a/Svelto.ECS/DataStructures/Unmanaged/ThreadSafeNativeBag.cs +++ b/Svelto.ECS/DataStructures/Unmanaged/ThreadSafeNativeBag.cs @@ -183,7 +183,7 @@ namespace Svelto.ECS.DataStructures } } -#if UNITY_COLLECTIONS +#if UNITY_COLLECTIONS || UNITY_JOBS || UNITY_BURST [global::Unity.Collections.LowLevel.Unsafe.NativeDisableUnsafePtrRestriction] #endif unsafe UnsafeBlob* _queue; diff --git a/Svelto.ECS/DataStructures/Unmanaged/UnsafeArray.cs b/Svelto.ECS/DataStructures/Unmanaged/UnsafeArray.cs index 668d543..89dda8e 100644 --- a/Svelto.ECS/DataStructures/Unmanaged/UnsafeArray.cs +++ b/Svelto.ECS/DataStructures/Unmanaged/UnsafeArray.cs @@ -133,7 +133,7 @@ namespace Svelto.ECS.DataStructures _writeIndex = count; } -#if UNITY_COLLECTIONS +#if UNITY_COLLECTIONS || UNITY_JOBS || UNITY_BURST [global::Unity.Collections.LowLevel.Unsafe.NativeDisableUnsafePtrRestriction] #endif unsafe byte* _ptr; diff --git a/Svelto.ECS/Extensions/Svelto/GroupsEnumerable.cs b/Svelto.ECS/Extensions/Svelto/GroupsEnumerable.cs index f5fbfc5..6425531 100644 --- a/Svelto.ECS/Extensions/Svelto/GroupsEnumerable.cs +++ b/Svelto.ECS/Extensions/Svelto/GroupsEnumerable.cs @@ -148,6 +148,8 @@ namespace Svelto.ECS readonly EntitiesDB _entitiesDB; } + //todo: there is a steep cost to pay to copy these structs, one day I may need to investigate this more. + //the structs are quite big, in the order of 100+ bytes. public GroupsIterator GetEnumerator() { return new GroupsIterator(_db, _groups); } readonly EntitiesDB _db; diff --git a/Svelto.ECS/Extensions/Unity/DOTS/Native/NativeEGIDMapper.cs b/Svelto.ECS/Extensions/Unity/DOTS/Native/NativeEGIDMapper.cs index cf953d8..628ef08 100644 --- a/Svelto.ECS/Extensions/Unity/DOTS/Native/NativeEGIDMapper.cs +++ b/Svelto.ECS/Extensions/Unity/DOTS/Native/NativeEGIDMapper.cs @@ -6,18 +6,28 @@ using Svelto.DataStructures; namespace Svelto.ECS.Native { - public readonly struct NativeEGIDMapper:IEGIDMapper where T : unmanaged, IEntityComponent + /// + /// Note: this class should really be ref struct by design. It holds the reference of a dictionary that can become + /// invalid. Unfortunately it can be a ref struct, because Jobs needs to hold if by paramater. So the deal is + /// that a job can use it as long as nothing else is modifying the entities database and the NativeEGIDMapper + /// is disposed right after the use. + /// + public readonly struct NativeEGIDMapper : IEGIDMapper where T : unmanaged, IEntityComponent { public NativeEGIDMapper - (ExclusiveGroupStruct groupStructId, SveltoDictionaryNative toNative) : this() + (ExclusiveGroupStruct groupStructId + , SveltoDictionary>, NativeStrategy, NativeStrategy> + toNative) : this() { groupID = groupStructId; - _map = toNative; + _map = new SveltoDictionaryNative(); + + _map.UnsafeCast(toNative); } - public int count => _map.count; - public Type entityType => TypeCache.type; - public ExclusiveGroupStruct groupID { get; } + public int count => _map.count; + public Type entityType => TypeCache.type; + public ExclusiveGroupStruct groupID { get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T Entity(uint entityID) @@ -35,14 +45,12 @@ namespace Svelto.ECS.Native public bool TryGetEntity(uint entityID, out T value) { if (_map.count > 0 && _map.TryFindIndex(entityID, out var index)) - { unsafe { value = Unsafe.AsRef(Unsafe.Add((void*) _map.GetValues(out _).ToNativeArray(out _) , (int) index)); return true; } - } value = default; return false; @@ -52,9 +60,7 @@ namespace Svelto.ECS.Native public NB GetArrayAndEntityIndex(uint entityID, out uint index) { if (_map.TryFindIndex(entityID, out index)) - { return new NB(_map.GetValues(out var count).ToNativeArray(out _), count); - } #if DEBUG throw new ECSException("Entity not found"); @@ -94,8 +100,8 @@ namespace Svelto.ECS.Native { return _map.TryFindIndex(valueKey, out index); } - - readonly ReadonlySveltoDictionaryNative _map; + + readonly SveltoDictionaryNative _map; } } #endif \ No newline at end of file diff --git a/Svelto.ECS/Extensions/Unity/DOTS/Native/NativeEGIDMultiMapper.cs b/Svelto.ECS/Extensions/Unity/DOTS/Native/NativeEGIDMultiMapper.cs index 94ba669..228cae0 100644 --- a/Svelto.ECS/Extensions/Unity/DOTS/Native/NativeEGIDMultiMapper.cs +++ b/Svelto.ECS/Extensions/Unity/DOTS/Native/NativeEGIDMultiMapper.cs @@ -4,6 +4,12 @@ using Svelto.DataStructures; namespace Svelto.ECS.Native { + /// + /// Note: this class should really be ref struct by design. It holds the reference of a dictionary that can become + /// invalid. Unfortunately it can be a ref struct, because Jobs needs to hold if by paramater. So the deal is + /// that a job can use it as long as nothing else is modifying the entities database and the NativeEGIDMultiMapper + /// is disposed right after the use. + /// public struct NativeEGIDMultiMapper : IDisposable where T : unmanaged, IEntityComponent { public NativeEGIDMultiMapper diff --git a/Svelto.ECS/Svelto.ECS.csproj b/Svelto.ECS/Svelto.ECS.csproj index 0644b97..982670d 100644 --- a/Svelto.ECS/Svelto.ECS.csproj +++ b/Svelto.ECS/Svelto.ECS.csproj @@ -3,6 +3,8 @@ Svelto.ECS 8 netstandard2.0 + Svelto + 3.2.1 Svelto.ECS @@ -23,6 +25,6 @@ - + \ No newline at end of file diff --git a/Svelto.ECS/package.json b/Svelto.ECS/package.json index b5abd7c..471ea37 100644 --- a/Svelto.ECS/package.json +++ b/Svelto.ECS/package.json @@ -3,13 +3,13 @@ "category": "Svelto", "description": "Svelto ECS C# Lightweight Data Oriented Entity Component System Framework", "dependencies": { - "com.sebaslab.svelto.common": "3.2.0" + "com.sebaslab.svelto.common": "3.2.1" }, "keywords": [ "svelto" ], "name": "com.sebaslab.svelto.ecs", - "version": "3.2.1", + "version": "3.2.2", "type": "library", "unity": "2019.3" } \ No newline at end of file diff --git a/Svelto.ECS/version.json b/Svelto.ECS/version.json index 7706f9e..3253af1 100644 --- a/Svelto.ECS/version.json +++ b/Svelto.ECS/version.json @@ -1,3 +1,3 @@ { - "version": "3.2.1" + "version": "3.2.2" }