using System; using System.Collections; using System.Collections.Generic; using System.Reflection; namespace Logic.Pool { /// /// Lightweight collection pool for temporary List/Dictionary/HashSet allocations. /// public static class THCollectionPool { private const int DefaultMaxPoolSizePerType = 256; private static class TypePool where T : class, new() { internal static readonly Stack Items = new Stack(32); internal static readonly object Sync = new object(); internal static readonly Action Reset = BuildResetAction(); private static Action BuildResetAction() { var type = typeof(T); if (typeof(IDictionary).IsAssignableFrom(type)) { return instance => ((IDictionary)instance).Clear(); } if (typeof(IList).IsAssignableFrom(type)) { return instance => ((IList)instance).Clear(); } var clearMethod = type.GetMethod("Clear", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null); if (clearMethod == null) { return _ => { }; } try { return (Action)Delegate.CreateDelegate(typeof(Action), null, clearMethod); } catch { return instance => clearMethod.Invoke(instance, null); } } } public static T Get() where T : class, new() { var pool = TypePool.Items; lock (TypePool.Sync) { if (pool.Count > 0) { return pool.Pop(); } } return new T(); } public static void Release(T instance) where T : class, new() { if (instance == null) { return; } TypePool.Reset(instance); var pool = TypePool.Items; lock (TypePool.Sync) { if (pool.Count >= DefaultMaxPoolSizePerType) { return; } pool.Push(instance); } } public static List GetList() { return Get>(); } public static Dictionary GetDictionary() { return Get>(); } public static HashSet GetHashSet() { return Get>(); } public static void ReleaseList(List instance) { Release(instance); } public static void ReleaseDictionary(Dictionary instance) { Release(instance); } public static void ReleaseHashSet(HashSet instance) { Release(instance); } public static PooledHandle> GetListHandle(out List instance) { instance = GetList(); return new PooledHandle>(instance); } public static PooledHandle> GetDictionaryHandle(out Dictionary instance) { instance = GetDictionary(); return new PooledHandle>(instance); } public static PooledHandle> GetHashSetHandle(out HashSet instance) { instance = GetHashSet(); return new PooledHandle>(instance); } } public readonly struct PooledHandle : IDisposable where T : class, new() { private readonly T _instance; public PooledHandle(T instance) { _instance = instance; } public void Dispose() { THCollectionPool.Release(_instance); } } }