| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- using System;
- using System.Collections.Generic;
- namespace Coffee.UIParticleInternal
- {
- /// <summary>
- /// Object pool.
- /// </summary>
- internal class InternalObjectPool<T> where T : class
- {
- #if UNITY_2021_1_OR_NEWER
- private readonly Predicate<T> _onValid; // Delegate for checking if instances are valid
- private readonly UnityEngine.Pool.ObjectPool<T> _pool;
- public InternalObjectPool(Func<T> onCreate, Predicate<T> onValid, Action<T> onReturn)
- {
- _pool = new UnityEngine.Pool.ObjectPool<T>(onCreate, null, onReturn);
- _onValid = onValid;
- }
- /// <summary>
- /// Rent an instance from the pool.
- /// When you no longer need it, return it with <see cref="Return" />.
- /// </summary>
- 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();
- }
- /// <summary>
- /// Return an instance to the pool and assign null.
- /// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
- /// </summary>
- 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<T> _onCreate; // Delegate for creating instances
- private readonly Action<T> _onReturn; // Delegate for returning instances to the pool
- private readonly Predicate<T> _onValid; // Delegate for checking if instances are valid
- private readonly Stack<T> _pool = new Stack<T>(32); // Object pool
- private int _count; // Total count of created instances
- public InternalObjectPool(Func<T> onCreate, Predicate<T> onValid, Action<T> onReturn)
- {
- _onCreate = onCreate;
- _onValid = onValid;
- _onReturn = onReturn;
- }
- /// <summary>
- /// Rent an instance from the pool.
- /// When you no longer need it, return it with <see cref="Return" />.
- /// </summary>
- 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();
- }
- /// <summary>
- /// Return an instance to the pool and assign null.
- /// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
- /// </summary>
- 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
- }
- /// <summary>
- /// Object pool for <see cref="List{T}" />.
- /// </summary>
- internal static class InternalListPool<T>
- {
- #if UNITY_2021_1_OR_NEWER
- /// <summary>
- /// Rent an instance from the pool.
- /// When you no longer need it, return it with <see cref="Return" />.
- /// </summary>
- public static List<T> Rent()
- {
- return UnityEngine.Pool.ListPool<T>.Get();
- }
- /// <summary>
- /// Return an instance to the pool and assign null.
- /// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
- /// </summary>
- public static void Return(ref List<T> toRelease)
- {
- if (toRelease != null)
- {
- UnityEngine.Pool.ListPool<T>.Release(toRelease);
- }
- toRelease = null;
- }
- #else
- private static readonly InternalObjectPool<List<T>> s_ListPool =
- new InternalObjectPool<List<T>>(() => new List<T>(), _ => true, x => x.Clear());
- /// <summary>
- /// Rent an instance from the pool.
- /// When you no longer need it, return it with <see cref="Return" />.
- /// </summary>
- public static List<T> Rent()
- {
- return s_ListPool.Rent();
- }
- /// <summary>
- /// Return an instance to the pool and assign null.
- /// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
- /// </summary>
- public static void Return(ref List<T> toRelease)
- {
- s_ListPool.Return(ref toRelease);
- }
- #endif
- }
- }
|