149 lines
4.1 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|