#if DEBUG && !PROFILE_SVELTO //#define PARANOID_CHECK #endif using System; using System.Runtime.CompilerServices; using System.Threading; using Svelto.Common; using Svelto.DataStructures; using Svelto.DataStructures.Native; namespace Svelto.ECS.Internal { #if SLOW_SVELTO_SUBMISSION static class SlowSubmissionInfo { internal static readonly bool hasEgid = typeof(INeedEGID).IsAssignableFrom(TypeCache.type); internal static readonly bool hasReference = typeof(INeedEntityReference).IsAssignableFrom(TypeCache.type); } #endif sealed class UnmanagedTypeSafeDictionary : ITypeSafeDictionary where TValue : struct, _IInternalEntityComponent { static readonly ThreadLocal cachedEntityIDN = new ThreadLocal(() => new NativeEntityIDs()); public UnmanagedTypeSafeDictionary(uint size) { implUnmgd = new SharedSveltoDictionaryNative(size, Allocator.Persistent); } public IEntityIDs entityIDs { get { ref var unboxed = ref Unsafe.Unbox(cachedEntityIDN.Value); unboxed.Update(implUnmgd.dictionary.unsafeKeys.ToRealBuffer()); return cachedEntityIDN.Value; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool ContainsKey(uint egidEntityId) { return implUnmgd.dictionary.ContainsKey(egidEntityId); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint GetIndex(uint valueEntityId) { return implUnmgd.dictionary.GetIndex(valueEntityId); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref TValue GetOrAdd(uint idEntityId) { return ref implUnmgd.dictionary.GetOrAdd(idEntityId); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public IBuffer GetValues(out uint count) { return implUnmgd.dictionary.UnsafeGetValues(out count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref TValue GetDirectValueByRef(uint key) { return ref implUnmgd.dictionary.GetDirectValueByRef(key); } public ref TValue GetValueByRef(uint key) { return ref implUnmgd.dictionary.GetValueByRef(key); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Has(uint key) { return implUnmgd.dictionary.ContainsKey(key); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryFindIndex(uint entityId, out uint index) { return implUnmgd.dictionary.TryFindIndex(entityId, out index); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGetValue(uint entityId, out TValue item) { return implUnmgd.dictionary.TryGetValue(entityId, out item); } public int count { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => implUnmgd.dictionary.count; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ITypeSafeDictionary Create() { return new UnmanagedTypeSafeDictionary(1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Clear() { implUnmgd.dictionary.Clear(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void EnsureCapacity(uint size) { implUnmgd.dictionary.EnsureCapacity(size); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void IncreaseCapacityBy(uint size) { implUnmgd.dictionary.IncreaseCapacityBy(size); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Trim() { implUnmgd.dictionary.Trim(); } public void KeysEvaluator(Action action) { foreach (var key in implUnmgd.dictionary.keys) action(key); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(uint egidEntityId, in TValue entityComponent) { implUnmgd.dictionary.Add(egidEntityId, entityComponent); } public void Dispose() { implUnmgd.Dispose(); //SharedDisposableNative already calls the dispose of the underlying value GC.SuppressFinalize(this); } /// ********************************* /// the following methods are executed during the submission of entities /// ********************************* [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AddEntitiesToDictionary (ITypeSafeDictionary toDictionary, ExclusiveGroupStruct groupId #if SLOW_SVELTO_SUBMISSION , in EnginesRoot.EntityReferenceMap entityLocator #endif ) { TypeSafeDictionaryMethods.AddEntitiesToDictionary(implUnmgd.dictionary , toDictionary as ITypeSafeDictionary #if SLOW_SVELTO_SUBMISSION , entityLocator #endif , groupId); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RemoveEntitiesFromDictionary (FasterList<(uint, string)> infosToProcess, FasterList entityIDsAffectedByRemoval) { TypeSafeDictionaryMethods.RemoveEntitiesFromDictionary(infosToProcess, ref implUnmgd.dictionary , entityIDsAffectedByRemoval); } public void SwapEntitiesBetweenDictionaries (FasterList<(uint, uint, string)> infosToProcess, ExclusiveGroupStruct fromGroup , ExclusiveGroupStruct toGroup, ITypeSafeDictionary toComponentsDictionary , FasterList entityIDsAffectedByRemoval) { TypeSafeDictionaryMethods.SwapEntitiesBetweenDictionaries(infosToProcess, ref implUnmgd.dictionary ,toComponentsDictionary as ITypeSafeDictionary, fromGroup, toGroup, entityIDsAffectedByRemoval); } /// /// Execute all the engine IReactOnAdd callbacks linked to components added this submit /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesAddCallbacks (FasterDictionary>> entityComponentEnginesDB , ITypeSafeDictionary toDic, ExclusiveGroupStruct toGroup, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesAddCallbacks(ref implUnmgd.dictionary, (ITypeSafeDictionary)toDic , toGroup, entityComponentEnginesDB, in profiler); } /// /// Execute all the engine IReactOnSwap callbacks linked to components swapped this submit /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesSwapCallbacks (FasterList<(uint, uint, string)> infosToProcess , FasterList> reactiveEnginesSwap, ExclusiveGroupStruct fromGroup , ExclusiveGroupStruct toGroup, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesSwapCallbacks(infosToProcess, ref implUnmgd.dictionary , reactiveEnginesSwap, toGroup, fromGroup, in profiler); } /// /// Execute all the engine IReactOnREmove callbacks linked to components removed this submit /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesRemoveCallbacks (FasterList<(uint, string)> infosToProcess , FasterDictionary>> reactiveEnginesRemove , ExclusiveGroupStruct fromGroup, in PlatformProfiler sampler) { TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacks(infosToProcess, ref implUnmgd.dictionary , reactiveEnginesRemove, fromGroup, in sampler); } /// /// Execute all the engine IReactOnAddEx callbacks linked to components added this submit /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesAddEntityCallbacksFast (FasterDictionary>> reactiveEnginesAdd , ExclusiveGroupStruct groupID, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesAddEntityCallbacksFast( reactiveEnginesAdd, groupID, rangeOfSubmittedEntitiesIndicies, entityIDs, this, profiler); } /// /// Execute all the engine IReactOnSwapEx callbacks linked to components swapped this submit /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesSwapCallbacksFast (FasterList> reactiveEnginesSwap, ExclusiveGroupStruct fromGroup , ExclusiveGroupStruct toGroup, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler sampler) { TypeSafeDictionaryMethods.ExecuteEnginesSwapCallbacksFast(reactiveEnginesSwap, fromGroup, toGroup, entityIDs , this, rangeOfSubmittedEntitiesIndicies, sampler); } /// /// Execute all the engine IReactOnRemoveEx callbacks linked to components removed this submit /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesRemoveCallbacksFast (FasterList> reactiveEnginesRemoveEx, ExclusiveGroupStruct fromGroup , (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler sampler) { TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacksFast(reactiveEnginesRemoveEx, fromGroup , rangeOfSubmittedEntitiesIndicies, entityIDs , this, sampler); } /// /// Execute all the engine IReactOnSwap and IReactOnSwapEx callbacks linked to components swapped between /// whole groups swapped during this submit /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesSwapCallbacks_Group (FasterDictionary>> reactiveEnginesSwap , FasterDictionary>> reactiveEnginesSwapEx , ITypeSafeDictionary toDictionary, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup , in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesSwapCallbacks_Group( ref implUnmgd.dictionary, (ITypeSafeDictionary)toDictionary, toGroup, fromGroup, this , reactiveEnginesSwap, reactiveEnginesSwapEx, count, entityIDs, in profiler); } /// /// Execute all the engine IReactOnRemove and IReactOnRemoveEx callbacks linked to components remove from /// whole groups removed during this submit /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesRemoveCallbacks_Group (FasterDictionary>> reactiveEnginesRemove , FasterDictionary>> reactiveEnginesRemoveEx , ExclusiveGroupStruct group, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesRemoveCallbacks_Group( ref implUnmgd.dictionary, this, reactiveEnginesRemove, reactiveEnginesRemoveEx, count, entityIDs, group , in profiler); } /// /// Execute all the engine IReactOnDispose for eahc component registered in the DB when it's disposed of /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ExecuteEnginesDisposeCallbacks_Group (FasterDictionary>> engines , ExclusiveGroupStruct group, in PlatformProfiler profiler) { TypeSafeDictionaryMethods.ExecuteEnginesDisposeCallbacks_Group( ref implUnmgd.dictionary, engines, group, in profiler); } internal SharedSveltoDictionaryNative implUnmgd; } }