using GameKit.Dependencies.Utilities.Types; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace GameKit.Dependencies.Utilities { /// /// Implement to use type with Caches. /// public interface IResettable { /// /// Resets values when being placed in a cache. /// void ResetState(); /// /// Initializes values after being retrieved from a cache. /// void InitializeState(); } #region Resettable caches. /// /// Caches collections of multiple generics. /// public static class ResettableCollectionCaches where T1 : IResettable, new() where T2 : IResettable, new() { /// /// Retrieves a collection. /// /// public static Dictionary RetrieveDictionary() => CollectionCaches.RetrieveDictionary(); /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref Dictionary value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(Dictionary value) { if (value == null) return; foreach (KeyValuePair kvp in value) { ResettableObjectCaches.Store(kvp.Key); ResettableObjectCaches.Store(kvp.Value); } value.Clear(); CollectionCaches.Store(value); } } /// /// Caches collections of multiple generics. /// public static class ResettableT1CollectionCaches where T1 : IResettable, new() { /// /// Retrieves a collection. /// /// public static Dictionary RetrieveDictionary() => CollectionCaches.RetrieveDictionary(); /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref Dictionary value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(Dictionary value) { if (value == null) return; foreach (T1 item in value.Keys) ResettableObjectCaches.Store(item); value.Clear(); CollectionCaches.Store(value); } } /// /// Caches collections of multiple generics. /// public static class ResettableT2CollectionCaches where T2 : IResettable, new() { /// /// Retrieves a collection. /// /// public static Dictionary RetrieveDictionary() => CollectionCaches.RetrieveDictionary(); /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref Dictionary value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(Dictionary value) { if (value == null) return; foreach (T2 item in value.Values) ResettableObjectCaches.Store(item); value.Clear(); CollectionCaches.Store(value); } } /// /// Caches collections of a single generic. /// public static class ResettableCollectionCaches where T : IResettable, new() { /// /// Cache for ResettableRingBuffer. /// private readonly static Stack> _resettableRingBufferCache = new(); /// /// Retrieves a collection. /// public static ResettableRingBuffer RetrieveRingBuffer() { ResettableRingBuffer result; if (!_resettableRingBufferCache.TryPop(out result)) result = new(); return result; } /// /// Retrieves a collection. /// /// public static T[] RetrieveArray() => CollectionCaches.RetrieveArray(); /// /// Retrieves a collection. /// /// public static List RetrieveList() => CollectionCaches.RetrieveList(); /// /// Retrieves a collection. /// /// public static HashSet RetrieveHashSet() => CollectionCaches.RetrieveHashSet(); /// /// Retrieves a collection. /// /// public static Queue RetrieveQueue() => CollectionCaches.RetrieveQueue(); /// /// Retrieves a collection. /// /// public static BasicQueue RetrieveBasicQueue() => CollectionCaches.RetrieveBasicQueue(); /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. /// Number of entries in the array from the beginning. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref ResettableRingBuffer value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. /// Number of entries in the array from the beginning. public static void Store(ResettableRingBuffer value) { if (value == null) return; value.ResetState(); _resettableRingBufferCache.Push(value); } /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. /// Number of entries in the array from the beginning. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref T[] value, int count) { Store(value, count); value = default; } /// /// Stores a collection. /// /// Value to store. /// Number of entries in the array from the beginning. public static void Store(T[] value, int count) { if (value == null) return; for (int i = 0; i < count; i++) ResettableObjectCaches.Store(value[i]); CollectionCaches.Store(value, count); } /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref List value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(List value) { if (value == null) return; for (int i = 0; i < value.Count; i++) ResettableObjectCaches.Store(value[i]); value.Clear(); CollectionCaches.Store(value); } /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref HashSet value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(HashSet value) { if (value == null) return; foreach (T item in value) ResettableObjectCaches.Store(item); value.Clear(); CollectionCaches.Store(value); } /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref Queue value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(Queue value) { if (value == null) return; foreach (T item in value) ResettableObjectCaches.Store(item); value.Clear(); CollectionCaches.Store(value); } /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref BasicQueue value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(BasicQueue value) { if (value == null) return; while (value.TryDequeue(out T result)) ResettableObjectCaches.Store(result); value.Clear(); CollectionCaches.Store(value); } } /// /// Caches objects of a single generic. /// public static class ResettableObjectCaches where T : IResettable, new() { /// /// Retrieves an instance of T. /// public static T Retrieve() { T result = ObjectCaches.Retrieve(); result.InitializeState(); return result; } /// /// Stores an instance of T and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref T value) { Store(value); value = default; } /// /// Stores an instance of T. /// /// Value to store. public static void Store(T value) { if (value == null) return; value.ResetState(); ObjectCaches.Store(value); } } #endregion #region NonResettable caches. /// /// Caches collections of multiple generics. /// public static class CollectionCaches { /// /// Cache for dictionaries. /// private static readonly Stack> _dictionaryCache = new(); /// /// Retrieves a collection. /// /// public static Dictionary RetrieveDictionary() { Dictionary result; if (!_dictionaryCache.TryPop(out result)) result = new(); return result; } /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref Dictionary value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(Dictionary value) { if (value == null) return; value.Clear(); _dictionaryCache.Push(value); } } /// /// Caches collections of a single generic. /// public static class CollectionCaches { /// /// Cache for arrays. /// private readonly static Stack _arrayCache = new(); /// /// Cache for lists. /// private readonly static Stack> _listCache = new(); /// /// Cache for queues. /// private readonly static Stack> _queueCache = new(); /// /// Cache for queues. /// private readonly static Stack> _basicQueueCache = new(); /// /// Cache for hashset. /// private readonly static Stack> _hashsetCache = new(); /// /// Retrieves a collection. /// /// public static T[] RetrieveArray() { T[] result; if (!_arrayCache.TryPop(out result)) result = new T[0]; return result; } /// /// Retrieves a collection. /// /// public static List RetrieveList() { List result; if (!_listCache.TryPop(out result)) result = new(); return result; } /// /// Retrieves a collection. /// /// public static Queue RetrieveQueue() { Queue result; if (!_queueCache.TryPop(out result)) result = new(); return result; } /// /// Retrieves a collection. /// /// public static BasicQueue RetrieveBasicQueue() { BasicQueue result; if (!_basicQueueCache.TryPop(out result)) result = new(); return result; } /// /// Retrieves a collection adding one entry. /// /// public static Queue RetrieveQueue(T entry) { Queue result; if (!_queueCache.TryPop(out result)) result = new(); result.Enqueue(entry); return result; } /// /// Retrieves a collection adding one entry. /// /// public static List RetrieveList(T entry) { List result; if (!_listCache.TryPop(out result)) result = new(); result.Add(entry); return result; } /// /// Retrieves a HashSet. /// /// public static HashSet RetrieveHashSet() { HashSet result; if (!_hashsetCache.TryPop(out result)) result = new(); return result; } /// /// Retrieves a collection adding one entry. /// /// public static HashSet RetrieveHashSet(T entry) { HashSet result; if (!_hashsetCache.TryPop(out result)) return new(); result.Add(entry); return result; } /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. /// Number of entries in the array set default, from the beginning. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref T[] value, int count) { Store(value, count); value = default; } /// /// Stores a collection. /// /// Value to store. /// Number of entries in the array from the beginning. public static void Store(T[] value, int count) { if (value == null) return; for (int i = 0; i < count; i++) value[i] = default; _arrayCache.Push(value); } /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref List value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(List value) { if (value == null) return; value.Clear(); _listCache.Push(value); } /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref Queue value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(Queue value) { if (value == null) return; value.Clear(); _queueCache.Push(value); } /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref BasicQueue value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(BasicQueue value) { if (value == null) return; value.Clear(); _basicQueueCache.Push(value); } /// /// Stores a collection and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref HashSet value) { Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(HashSet value) { if (value == null) return; value.Clear(); _hashsetCache.Push(value); } } /// /// Caches objects of a single generic. /// public static class ObjectCaches where T : new() { /// /// Stack to use. /// private static readonly Stack _stack = new(); /// /// Returns a value from the stack or creates an instance when the stack is empty. /// /// public static T Retrieve() { T result; if (!_stack.TryPop(out result)) result = new(); // Activator.CreateInstance(); return result; } /// /// Stores an instance of T and sets the original reference to default. /// Method will not execute if value is null. /// /// Value to store. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref T value) { Store(value); value = default; } /// /// Stores a value to the stack. /// /// public static void Store(T value) { if (value == null) return; _stack.Push(value); } } #endregion }