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