using System;
using System.Collections.Generic;
namespace Coffee.UIParticleInternal
{
///
/// Object pool.
///
internal class InternalObjectPool where T : class
{
#if UNITY_2021_1_OR_NEWER
private readonly Predicate _onValid; // Delegate for checking if instances are valid
private readonly UnityEngine.Pool.ObjectPool _pool;
public InternalObjectPool(Func onCreate, Predicate onValid, Action onReturn)
{
_pool = new UnityEngine.Pool.ObjectPool(onCreate, null, onReturn);
_onValid = onValid;
}
///
/// Rent an instance from the pool.
/// When you no longer need it, return it with .
///
public T Rent()
{
while (0 < _pool.CountInactive)
{
var instance = _pool.Get();
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.CountInactive}, created: {_pool.CountAll}).");
return _pool.Get();
}
///
/// 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) return; // Ignore if already pooled or null.
_pool.Release(instance);
Logging.Log(this, $"An instance is released (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
instance = default; // Set the reference to null.
}
#else
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 InternalObjectPool(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.
}
#endif
}
///
/// Object pool for .
///
internal static class InternalListPool
{
#if UNITY_2021_1_OR_NEWER
///
/// Rent an instance from the pool.
/// When you no longer need it, return it with .
///
public static List Rent()
{
return UnityEngine.Pool.ListPool.Get();
}
///
/// 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)
{
if (toRelease != null)
{
UnityEngine.Pool.ListPool.Release(toRelease);
}
toRelease = null;
}
#else
private static readonly InternalObjectPool> s_ListPool =
new InternalObjectPool>(() => 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);
}
#endif
}
}