// /* This implementation uses better naming as well provides // * a few new features. // * // * Object and Collection caches are now one class. */ // // // TODO In V5 disappear ResettableRingBuffer and have regular check implementation on start -- this will let us use this class for caching ringbuffer with resettable types. // using System; // using System.Collections; // 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(); // } // // public static class ResettableObjectPool where T : IResettable, new() { } // // /// // /// Caches collections and objects of T. // /// // public static class ObjectPool where T : new() // { // /// // /// Cache for List. // /// // private static readonly Stack> _listCache = new(); // /// // /// Resettable cache for List. // /// // private static readonly Stack> _resettableListCache = new(); // // /// // /// Cache for HashSet. // /// // private static readonly Stack> _hashSetCache = new(); // /// // /// Resettable cache for HashSet. // /// // private static readonly Stack> _resettableHashSetCache = new(); // // /// // /// Cache for Queue. // /// // private static readonly Stack> _queueCache = new(); // /// // /// Resettable cache for Queue. // /// // private static readonly Stack> _resettableQueueCache = new(); // // /// // /// Cache for T[]. // /// // private static readonly Stack _arrayCache = new(); // /// // /// Resettable cache for T[]. // /// // private static readonly Stack _resettableArrayCache = new(); // // /// // /// Cache for T. // /// // private static readonly Stack _tCache = new(); // /// // /// Resettable cache for T. // /// // private static readonly Stack _resettableTCache = new(); // // /// // /// True if T is a value type. // /// // private static readonly bool _isValueType; // /// // /// True if T implements IResettable. // /// // private static readonly bool _isResettable; // // static ObjectPool() // { // // Used at runtime to prevent nested collections. // bool isTCollection = typeof(ICollection).IsAssignableFrom(typeof(T)); // // if (isTCollection) // throw new NotSupportedException($"ObjectPool element cannot be a collection. Type is [{typeof(T).FullName}]."); // // _isValueType = typeof(T).IsValueType; // _isResettable = typeof(T).IsAssignableFrom(typeof(IResettable)); // } // // /// // /// Clears all pools for T. // /// // public static void ClearPools() // { // _listCache.Clear(); // _resettableListCache.Clear(); // // _hashSetCache.Clear(); // _resettableHashSetCache.Clear(); // // _queueCache.Clear(); // _resettableQueueCache.Clear(); // // _arrayCache.Clear(); // _resettableArrayCache.Clear(); // // _tCache.Clear(); // _resettableTCache.Clear(); // } // // /// // /// Returns a List automatically resetting entries when IResettable is implemented, // /// and pooling entries when they are a reference type. // /// // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static void Return(List value) // { // if (value == null) return; // // Stack> stack = _isResettable ? _resettableListCache : _listCache; // // IterateICollectionElements(value); // // value.Clear(); // stack.Push(value); // } // // /// // /// Returns a HashSet automatically resetting entries when IResettable is implemented, // /// and pooling entries when they are a reference type. // /// // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static void Return(HashSet value) // { // if (value == null) return; // // Stack> stack = _isResettable ? _resettableHashSetCache : _hashSetCache; // // IterateICollectionElements(value); // // value.Clear(); // stack.Push(value); // } // // /// // /// Returns a Queue automatically resetting entries when IResettable is implemented, // /// and pooling entries when they are a reference type. // /// // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static void Return(Queue value) // { // if (value == null) return; // // Stack> stack = _isResettable ? _resettableQueueCache : _queueCache; // // IterateICollectionElements(value); // // value.Clear(); // stack.Push(value); // } // // /// // /// Returns an array automatically resetting entries when IResettable is implemented, // /// and pools each array entry if the array element is a reference type. // /// // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static void Return(T[] value) // { // if (value == null) return; // // Stack stack = _isResettable ? _resettableArrayCache : _arrayCache; // // IterateICollectionElements(value); // // Array.Clear(value, 0, value.Length); // stack.Push(value); // } // // /// // /// Returns value without resetting the state. // /// // public static void Return(T value) // { // _tCache.Push(value); // } // // /// // /// Creates a new List. // /// // private static List CreateList() => new(); // // /// // /// Creates a new HashSet. // /// // private static HashSet CreateHashSet() => new(); // // /// // /// Creates a new Queue. // /// // private static Queue CreateQueue() => new(); // // /// // /// Creates a new array of length 0 (empty array). // /// // private static T[] CreateArray() => Array.Empty(); // // /// // /// Rents a List. // /// // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static List RentList() // { // Stack> stack = _isResettable ? _resettableListCache : _listCache; // // return RentCollection(stack, CreateList); // } // // /// // /// Rents a HashSet. // /// // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static HashSet RentHashSet() // { // Stack> stack = _isResettable ? _resettableHashSetCache : _hashSetCache; // // return RentCollection(stack, CreateHashSet); // } // // /// // /// Rents a Queue. // /// // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static Queue RentQueue() // { // Stack> stack = _isResettable ? _resettableQueueCache : _queueCache; // // return RentCollection(stack, CreateQueue); // } // // /// // /// Rents an array. // /// // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static T[] RentArray() // { // Stack stack = _isResettable ? _resettableArrayCache : _arrayCache; // // return RentCollection(stack, CreateArray); // } // // /// // /// Rents an object. // /// // public static T Rent() // { // Stack stack = _isResettable ? _resettableTCache : _tCache; // // if (!stack.TryPop(out T result)) // result = new(); // // return result; // } // // /// // /// Rents a collection using the supplied stack. Returns using defaultFactory if stack is empty. // /// // private static TCollection RentCollection(Stack stack, Func defaultFactory) // { // if (!stack.TryPop(out TCollection result)) // result = defaultFactory(); // // return result; // } // // /// // /// Iterates ICollection elements, returning and resetting as needed. // /// // [MethodImpl(MethodImplOptions.AggressiveInlining)] // private static void IterateICollectionElements(IReadOnlyCollection value) // { // // Reset T if possible. // if (_isResettable) // { // // Value type. // if (_isValueType) // { // foreach (T item in value) // ((IResettable)item).ResetState(); // } // // Reference type. // else // { // foreach (T item in value) // ReturnReferenceIResettable(item); // } // } // // Type is not resettable. // else // { // // Only need to Return if is not a value type. // if (!_isValueType) // { // foreach (T item in value) // ReturnReference(item); // } // } // } // // /// // /// Returns value expecting it to be a reference type that does not implement IResettable. // /// // private static void ReturnReference(T value) // { // _resettableTCache.Push(value); // } // // /// // /// Returns value expecting it to be a reference type which implement IResettable. // /// // internal static void ReturnReferenceIResettable(T value) // { // ((IResettable)value).ResetState(); // // _resettableTCache.Push(value); // } // } // }