A game about forced loneliness, made by TACStudios
1using System; 2using System.Collections.Generic; 3using UnityEngine.Events; 4 5namespace UnityEngine.Rendering 6{ 7 /// <summary> 8 /// Generic object pool. 9 /// </summary> 10 /// <typeparam name="T">Type of the object pool.</typeparam> 11 public class ObjectPool<T> where T : new() 12 { 13 readonly Stack<T> m_Stack = new Stack<T>(); 14 readonly UnityAction<T> m_ActionOnGet; 15 readonly UnityAction<T> m_ActionOnRelease; 16 readonly bool m_CollectionCheck = true; 17 18 /// <summary> 19 /// Number of objects in the pool. 20 /// </summary> 21 public int countAll { get; private set; } 22 /// <summary> 23 /// Number of active objects in the pool. 24 /// </summary> 25 public int countActive { get { return countAll - countInactive; } } 26 /// <summary> 27 /// Number of inactive objects in the pool. 28 /// </summary> 29 public int countInactive { get { return m_Stack.Count; } } 30 31 /// <summary> 32 /// Constructor. 33 /// </summary> 34 /// <param name="actionOnGet">Action on get.</param> 35 /// <param name="actionOnRelease">Action on release.</param> 36 /// <param name="collectionCheck">True if collection integrity should be checked.</param> 37 public ObjectPool(UnityAction<T> actionOnGet, UnityAction<T> actionOnRelease, bool collectionCheck = true) 38 { 39 m_ActionOnGet = actionOnGet; 40 m_ActionOnRelease = actionOnRelease; 41 m_CollectionCheck = collectionCheck; 42 } 43 44 /// <summary> 45 /// Get an object from the pool. 46 /// </summary> 47 /// <returns>A new object from the pool.</returns> 48 public T Get() 49 { 50 T element; 51 if (m_Stack.Count == 0) 52 { 53 element = new T(); 54 countAll++; 55 } 56 else 57 { 58 element = m_Stack.Pop(); 59 } 60 if (m_ActionOnGet != null) 61 m_ActionOnGet(element); 62 return element; 63 } 64 65 /// <summary> 66 /// Pooled object. 67 /// </summary> 68 public struct PooledObject : IDisposable 69 { 70 readonly T m_ToReturn; 71 readonly ObjectPool<T> m_Pool; 72 73 internal PooledObject(T value, ObjectPool<T> pool) 74 { 75 m_ToReturn = value; 76 m_Pool = pool; 77 } 78 79 /// <summary> 80 /// Disposable pattern implementation. 81 /// </summary> 82 void IDisposable.Dispose() => m_Pool.Release(m_ToReturn); 83 } 84 85 /// <summary> 86 /// Get et new PooledObject. 87 /// </summary> 88 /// <param name="v">Output new typed object.</param> 89 /// <returns>New PooledObject</returns> 90 public PooledObject Get(out T v) => new PooledObject(v = Get(), this); 91 92 /// <summary> 93 /// Release an object to the pool. 94 /// </summary> 95 /// <param name="element">Object to release.</param> 96 public void Release(T element) 97 { 98#if UNITY_EDITOR // keep heavy checks in editor 99 if (m_CollectionCheck && m_Stack.Count > 0) 100 { 101 if (m_Stack.Contains(element)) 102 Debug.LogError("Internal error. Trying to destroy object that is already released to pool."); 103 } 104#endif 105 if (m_ActionOnRelease != null) 106 m_ActionOnRelease(element); 107 m_Stack.Push(element); 108 } 109 } 110 111 /// <summary> 112 /// Generic pool. 113 /// </summary> 114 /// <typeparam name="T">Type of the objects in the pull.</typeparam> 115 public static class GenericPool<T> 116 where T : new() 117 { 118 // Object pool to avoid allocations. 119 static readonly ObjectPool<T> s_Pool = new ObjectPool<T>(null, null); 120 121 /// <summary> 122 /// Get a new object. 123 /// </summary> 124 /// <returns>A new object from the pool.</returns> 125 public static T Get() => s_Pool.Get(); 126 127 /// <summary> 128 /// Get a new PooledObject 129 /// </summary> 130 /// <param name="value">Output typed object.</param> 131 /// <returns>A new PooledObject.</returns> 132 public static ObjectPool<T>.PooledObject Get(out T value) => s_Pool.Get(out value); 133 134 /// <summary> 135 /// Release an object to the pool. 136 /// </summary> 137 /// <param name="toRelease">Object to release.</param> 138 public static void Release(T toRelease) => s_Pool.Release(toRelease); 139 } 140 141 /// <summary> 142 /// Generic pool without collection checks. 143 /// This class is an alternative for the GenericPool for object that allocate memory when they are being compared. 144 /// It is the case for the CullingResult class from Unity, and because of this in HDRP HDCullingResults generates garbage whenever we use ==, .Equals or ReferenceEquals. 145 /// This pool doesn't do any of these comparison because we don't check if the stack already contains the element before releasing it. 146 /// </summary> 147 /// <typeparam name="T">Type of the objects in the pull.</typeparam> 148 public static class UnsafeGenericPool<T> 149 where T : new() 150 { 151 // Object pool to avoid allocations. 152 static readonly ObjectPool<T> s_Pool = new ObjectPool<T>(null, null, false); 153 154 /// <summary> 155 /// Get a new object. 156 /// </summary> 157 /// <returns>A new object from the pool.</returns> 158 public static T Get() => s_Pool.Get(); 159 160 /// <summary> 161 /// Get a new PooledObject 162 /// </summary> 163 /// <param name="value">Output typed object.</param> 164 /// <returns>A new PooledObject.</returns> 165 public static ObjectPool<T>.PooledObject Get(out T value) => s_Pool.Get(out value); 166 167 /// <summary> 168 /// Release an object to the pool. 169 /// </summary> 170 /// <param name="toRelease">Object to release.</param> 171 public static void Release(T toRelease) => s_Pool.Release(toRelease); 172 } 173 174 /// <summary> 175 /// List Pool. 176 /// </summary> 177 /// <typeparam name="T">Type of the objects in the pooled lists.</typeparam> 178 public static class ListPool<T> 179 { 180 // Object pool to avoid allocations. 181 static readonly ObjectPool<List<T>> s_Pool = new ObjectPool<List<T>>(null, l => l.Clear()); 182 183 /// <summary> 184 /// Get a new List 185 /// </summary> 186 /// <returns>A new List</returns> 187 public static List<T> Get() => s_Pool.Get(); 188 189 /// <summary> 190 /// Get a new list PooledObject. 191 /// </summary> 192 /// <param name="value">Output typed List.</param> 193 /// <returns>A new List PooledObject.</returns> 194 public static ObjectPool<List<T>>.PooledObject Get(out List<T> value) => s_Pool.Get(out value); 195 196 /// <summary> 197 /// Release an object to the pool. 198 /// </summary> 199 /// <param name="toRelease">List to release.</param> 200 public static void Release(List<T> toRelease) => s_Pool.Release(toRelease); 201 } 202 203 /// <summary> 204 /// HashSet Pool. 205 /// </summary> 206 /// <typeparam name="T">Type of the objects in the pooled hashsets.</typeparam> 207 public static class HashSetPool<T> 208 { 209 // Object pool to avoid allocations. 210 static readonly ObjectPool<HashSet<T>> s_Pool = new ObjectPool<HashSet<T>>(null, l => l.Clear()); 211 212 /// <summary> 213 /// Get a new HashSet 214 /// </summary> 215 /// <returns>A new HashSet</returns> 216 public static HashSet<T> Get() => s_Pool.Get(); 217 218 /// <summary> 219 /// Get a new list PooledObject. 220 /// </summary> 221 /// <param name="value">Output typed HashSet.</param> 222 /// <returns>A new HashSet PooledObject.</returns> 223 public static ObjectPool<HashSet<T>>.PooledObject Get(out HashSet<T> value) => s_Pool.Get(out value); 224 225 /// <summary> 226 /// Release an object to the pool. 227 /// </summary> 228 /// <param name="toRelease">hashSet to release.</param> 229 public static void Release(HashSet<T> toRelease) => s_Pool.Release(toRelease); 230 } 231 232 /// <summary> 233 /// Dictionary Pool. 234 /// </summary> 235 /// <typeparam name="TKey">Key type.</typeparam> 236 /// <typeparam name="TValue">Value type.</typeparam> 237 public static class DictionaryPool<TKey, TValue> 238 { 239 // Object pool to avoid allocations. 240 static readonly ObjectPool<Dictionary<TKey, TValue>> s_Pool 241 = new ObjectPool<Dictionary<TKey, TValue>>(null, l => l.Clear()); 242 243 /// <summary> 244 /// Get a new Dictionary 245 /// </summary> 246 /// <returns>A new Dictionary</returns> 247 public static Dictionary<TKey, TValue> Get() => s_Pool.Get(); 248 249 /// <summary> 250 /// Get a new dictionary PooledObject. 251 /// </summary> 252 /// <param name="value">Output typed Dictionary.</param> 253 /// <returns>A new Dictionary PooledObject.</returns> 254 public static ObjectPool<Dictionary<TKey, TValue>>.PooledObject Get(out Dictionary<TKey, TValue> value) 255 => s_Pool.Get(out value); 256 257 /// <summary> 258 /// Release an object to the pool. 259 /// </summary> 260 /// <param name="toRelease">Dictionary to release.</param> 261 public static void Release(Dictionary<TKey, TValue> toRelease) => s_Pool.Release(toRelease); 262 } 263}