TH1/Unity/Assets/Scripts/TH1_Logic/Pool/THCollectionPool.cs
2026-04-24 18:22:21 +08:00

149 lines
4.1 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
namespace Logic.Pool
{
/// <summary>
/// Lightweight collection pool for temporary List/Dictionary/HashSet allocations.
/// </summary>
public static class THCollectionPool
{
private const int DefaultMaxPoolSizePerType = 256;
private static class TypePool<T> where T : class, new()
{
internal static readonly Stack<T> Items = new Stack<T>(32);
internal static readonly object Sync = new object();
internal static readonly Action<T> Reset = BuildResetAction();
private static Action<T> 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<T>)Delegate.CreateDelegate(typeof(Action<T>), null, clearMethod);
}
catch
{
return instance => clearMethod.Invoke(instance, null);
}
}
}
public static T Get<T>() where T : class, new()
{
var pool = TypePool<T>.Items;
lock (TypePool<T>.Sync)
{
if (pool.Count > 0)
{
return pool.Pop();
}
}
return new T();
}
public static void Release<T>(T instance) where T : class, new()
{
if (instance == null)
{
return;
}
TypePool<T>.Reset(instance);
var pool = TypePool<T>.Items;
lock (TypePool<T>.Sync)
{
if (pool.Count >= DefaultMaxPoolSizePerType)
{
return;
}
pool.Push(instance);
}
}
public static List<T> GetList<T>()
{
return Get<List<T>>();
}
public static Dictionary<TKey, TValue> GetDictionary<TKey, TValue>()
{
return Get<Dictionary<TKey, TValue>>();
}
public static HashSet<T> GetHashSet<T>()
{
return Get<HashSet<T>>();
}
public static void ReleaseList<T>(List<T> instance)
{
Release(instance);
}
public static void ReleaseDictionary<TKey, TValue>(Dictionary<TKey, TValue> instance)
{
Release(instance);
}
public static void ReleaseHashSet<T>(HashSet<T> instance)
{
Release(instance);
}
public static PooledHandle<List<T>> GetListHandle<T>(out List<T> instance)
{
instance = GetList<T>();
return new PooledHandle<List<T>>(instance);
}
public static PooledHandle<Dictionary<TKey, TValue>> GetDictionaryHandle<TKey, TValue>(out Dictionary<TKey, TValue> instance)
{
instance = GetDictionary<TKey, TValue>();
return new PooledHandle<Dictionary<TKey, TValue>>(instance);
}
public static PooledHandle<HashSet<T>> GetHashSetHandle<T>(out HashSet<T> instance)
{
instance = GetHashSet<T>();
return new PooledHandle<HashSet<T>>(instance);
}
}
public readonly struct PooledHandle<T> : IDisposable where T : class, new()
{
private readonly T _instance;
public PooledHandle(T instance)
{
_instance = instance;
}
public void Dispose()
{
THCollectionPool.Release(_instance);
}
}
}