// /* 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);
// }
// }
// }