using System; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace GameKit.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 where T2 : IResettable { /// /// 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) { if (value == null) return; Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(Dictionary value) { foreach (KeyValuePair kvp in value) { kvp.Key.ResetState(); ObjectCaches.Store(kvp.Key); kvp.Value.ResetState(); ObjectCaches.Store(kvp.Value); } value.Clear(); CollectionCaches.Store(value); } } /// /// Caches collections of multiple generics. /// public static class ResettableT1CollectionCaches where T1 : IResettable { /// /// 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) { if (value == null) return; Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(Dictionary value) { foreach (T1 item in value.Keys) { item.ResetState(); ObjectCaches.Store(item); } value.Clear(); CollectionCaches.Store(value); } } /// /// Caches collections of multiple generics. /// public static class ResettableT2CollectionCaches where T2 : IResettable { /// /// 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) { if (value == null) return; Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(Dictionary value) { foreach (T2 item in value.Values) { item.ResetState(); ObjectCaches.Store(item); } value.Clear(); CollectionCaches.Store(value); } } /// /// Caches collections of a single generic. /// public static class ResettableCollectionCaches where T : IResettable { /// /// 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(); /// /// 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) { if (value == null) return; 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) { for (int i = 0; i < count; i++) { value[i].ResetState(); ObjectCaches.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) { if (value == null) return; Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(List value) { for (int i = 0; i < value.Count; i++) { value[i].ResetState(); ObjectCaches.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) { if (value == null) return; Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(HashSet value) { foreach (T item in value) { item.ResetState(); ObjectCaches.Store(item); } value.Clear(); CollectionCaches.Store(value); } } /// /// Caches objects of a single generic. /// public static class ResettableObjectCaches where T : IResettable { /// /// 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) { if (value == null) return; Store(value); value = default; } /// /// Stores an instance of T. /// /// Value to store. public static void Store(T value) { value.ResetState(); ObjectCaches.Store(value); } } #endregion #region NonResettable caches. /// /// Caches collections of multiple generics. /// public static class CollectionCaches { /// /// Cache for dictionaries. /// private readonly static Stack> _dictionaryCache = new Stack>(); /// /// Retrieves a collection. /// /// public static Dictionary RetrieveDictionary() { if (_dictionaryCache.Count == 0) return new Dictionary(); else return _dictionaryCache.Pop(); } /// /// 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) { if (value == null) return; Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(Dictionary value) { value.Clear(); _dictionaryCache.Push(value); } } /// /// Caches collections of a single generic. /// public static class CollectionCaches { /// /// Cache for arrays. /// private readonly static Stack _arrayCache = new Stack(); /// /// Cache for lists. /// private readonly static Stack> _listCache = new Stack>(); /// /// Cache for hashset. /// private readonly static Stack> _hashsetCache = new Stack>(); /// /// Retrieves a collection. /// /// public static T[] RetrieveArray() { if (_arrayCache.Count == 0) return new T[0]; else return _arrayCache.Pop(); } /// /// Retrieves a collection. /// /// public static List RetrieveList() { if (_listCache.Count == 0) return new List(); else return _listCache.Pop(); } /// /// Retrieves a collection adding one entry. /// /// public static List RetrieveList(T entry) { List result; if (_listCache.Count == 0) result = new List(); else result = _listCache.Pop(); result.Add(entry); return result; } /// /// Retrieves a HashSet. /// /// public static HashSet RetrieveHashSet() { if (_hashsetCache.Count == 0) return new HashSet(); else return _hashsetCache.Pop(); } /// /// Retrieves a collection adding one entry. /// /// public static HashSet RetrieveHashSet(T entry) { HashSet result; if (_hashsetCache.Count == 0) result = new HashSet(); else result = _hashsetCache.Pop(); 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 from the beginning. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void StoreAndDefault(ref T[] value, int count) { if (value == null) return; 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) { 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) { if (value == null) return; Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(List value) { 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 HashSet value) { if (value == null) return; Store(value); value = default; } /// /// Stores a collection. /// /// Value to store. public static void Store(HashSet value) { value.Clear(); _hashsetCache.Push(value); } } /// /// Caches objects of a single generic. /// public static class ObjectCaches { /// /// Stack to use. /// private readonly static Stack _stack = new Stack(); /// /// Returns a value from the stack or creates an instance when the stack is empty. /// /// public static T Retrieve() { if (_stack.Count == 0) return Activator.CreateInstance(); else return _stack.Pop(); } /// /// 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) { if (value == null) return; Store(value); value = default; } /// /// Stores a value to the stack. /// /// public static void Store(T value) { _stack.Push(value); } } #endregion }