ObjectPool.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Coffee.UIParticleInternal
  4. {
  5. /// <summary>
  6. /// Object pool.
  7. /// </summary>
  8. internal class InternalObjectPool<T> where T : class
  9. {
  10. #if UNITY_2021_1_OR_NEWER
  11. private readonly Predicate<T> _onValid; // Delegate for checking if instances are valid
  12. private readonly UnityEngine.Pool.ObjectPool<T> _pool;
  13. public InternalObjectPool(Func<T> onCreate, Predicate<T> onValid, Action<T> onReturn)
  14. {
  15. _pool = new UnityEngine.Pool.ObjectPool<T>(onCreate, null, onReturn);
  16. _onValid = onValid;
  17. }
  18. /// <summary>
  19. /// Rent an instance from the pool.
  20. /// When you no longer need it, return it with <see cref="Return" />.
  21. /// </summary>
  22. public T Rent()
  23. {
  24. while (0 < _pool.CountInactive)
  25. {
  26. var instance = _pool.Get();
  27. if (_onValid(instance))
  28. {
  29. return instance;
  30. }
  31. }
  32. // If there are no instances in the pool, create a new one.
  33. Logging.Log(this, $"A new instance is created (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
  34. return _pool.Get();
  35. }
  36. /// <summary>
  37. /// Return an instance to the pool and assign null.
  38. /// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
  39. /// </summary>
  40. public void Return(ref T instance)
  41. {
  42. if (instance == null) return; // Ignore if already pooled or null.
  43. _pool.Release(instance);
  44. Logging.Log(this, $"An instance is released (pooled: {_pool.CountInactive}, created: {_pool.CountAll}).");
  45. instance = default; // Set the reference to null.
  46. }
  47. #else
  48. private readonly Func<T> _onCreate; // Delegate for creating instances
  49. private readonly Action<T> _onReturn; // Delegate for returning instances to the pool
  50. private readonly Predicate<T> _onValid; // Delegate for checking if instances are valid
  51. private readonly Stack<T> _pool = new Stack<T>(32); // Object pool
  52. private int _count; // Total count of created instances
  53. public InternalObjectPool(Func<T> onCreate, Predicate<T> onValid, Action<T> onReturn)
  54. {
  55. _onCreate = onCreate;
  56. _onValid = onValid;
  57. _onReturn = onReturn;
  58. }
  59. /// <summary>
  60. /// Rent an instance from the pool.
  61. /// When you no longer need it, return it with <see cref="Return" />.
  62. /// </summary>
  63. public T Rent()
  64. {
  65. while (0 < _pool.Count)
  66. {
  67. var instance = _pool.Pop();
  68. if (_onValid(instance))
  69. {
  70. return instance;
  71. }
  72. }
  73. // If there are no instances in the pool, create a new one.
  74. Logging.Log(this, $"A new instance is created (pooled: {_pool.Count}, created: {++_count}).");
  75. return _onCreate();
  76. }
  77. /// <summary>
  78. /// Return an instance to the pool and assign null.
  79. /// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
  80. /// </summary>
  81. public void Return(ref T instance)
  82. {
  83. if (instance == null || _pool.Contains(instance)) return; // Ignore if already pooled or null.
  84. _onReturn(instance); // Return the instance to the pool.
  85. _pool.Push(instance);
  86. Logging.Log(this, $"An instance is released (pooled: {_pool.Count}, created: {_count}).");
  87. instance = default; // Set the reference to null.
  88. }
  89. #endif
  90. }
  91. /// <summary>
  92. /// Object pool for <see cref="List{T}" />.
  93. /// </summary>
  94. internal static class InternalListPool<T>
  95. {
  96. #if UNITY_2021_1_OR_NEWER
  97. /// <summary>
  98. /// Rent an instance from the pool.
  99. /// When you no longer need it, return it with <see cref="Return" />.
  100. /// </summary>
  101. public static List<T> Rent()
  102. {
  103. return UnityEngine.Pool.ListPool<T>.Get();
  104. }
  105. /// <summary>
  106. /// Return an instance to the pool and assign null.
  107. /// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
  108. /// </summary>
  109. public static void Return(ref List<T> toRelease)
  110. {
  111. if (toRelease != null)
  112. {
  113. UnityEngine.Pool.ListPool<T>.Release(toRelease);
  114. }
  115. toRelease = null;
  116. }
  117. #else
  118. private static readonly InternalObjectPool<List<T>> s_ListPool =
  119. new InternalObjectPool<List<T>>(() => new List<T>(), _ => true, x => x.Clear());
  120. /// <summary>
  121. /// Rent an instance from the pool.
  122. /// When you no longer need it, return it with <see cref="Return" />.
  123. /// </summary>
  124. public static List<T> Rent()
  125. {
  126. return s_ListPool.Rent();
  127. }
  128. /// <summary>
  129. /// Return an instance to the pool and assign null.
  130. /// Be sure to return the instance obtained with <see cref="Rent" /> with this method.
  131. /// </summary>
  132. public static void Return(ref List<T> toRelease)
  133. {
  134. s_ListPool.Return(ref toRelease);
  135. }
  136. #endif
  137. }
  138. }