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}