using System; using System.Collections.Generic; namespace Coffee.UIParticleInternal { /// /// Object pool. /// internal class ObjectPool { private readonly Func _onCreate; // Delegate for creating instances private readonly Action _onReturn; // Delegate for returning instances to the pool private readonly Predicate _onValid; // Delegate for checking if instances are valid private readonly Stack _pool = new Stack(32); // Object pool private int _count; // Total count of created instances public ObjectPool(Func onCreate, Predicate onValid, Action onReturn) { _onCreate = onCreate; _onValid = onValid; _onReturn = onReturn; } /// /// Rent an instance from the pool. /// When you no longer need it, return it with . /// public T Rent() { while (0 < _pool.Count) { var instance = _pool.Pop(); if (_onValid(instance)) { return instance; } } // If there are no instances in the pool, create a new one. Logging.Log(this, $"A new instance is created (pooled: {_pool.Count}, created: {++_count})."); return _onCreate(); } /// /// Return an instance to the pool and assign null. /// Be sure to return the instance obtained with with this method. /// public void Return(ref T instance) { if (instance == null || _pool.Contains(instance)) return; // Ignore if already pooled or null. _onReturn(instance); // Return the instance to the pool. _pool.Push(instance); Logging.Log(this, $"An instance is released (pooled: {_pool.Count}, created: {_count})."); instance = default; // Set the reference to null. } } /// /// Object pool for . /// internal static class ListPool { private static readonly ObjectPool> s_ListPool = new ObjectPool>(() => new List(), _ => true, x => x.Clear()); /// /// Rent an instance from the pool. /// When you no longer need it, return it with . /// public static List Rent() { return s_ListPool.Rent(); } /// /// Return an instance to the pool and assign null. /// Be sure to return the instance obtained with with this method. /// public static void Return(ref List toRelease) { s_ListPool.Return(ref toRelease); } } }