forked from Unity-Technologies/UnityCsReference
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathObjectPools.cs
More file actions
140 lines (124 loc) · 5.5 KB
/
Copy pathObjectPools.cs
File metadata and controls
140 lines (124 loc) · 5.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using System;
using System.Collections.Generic;
namespace UnityEngine.Pool
{
/// <summary>
/// Generic object pool implementation.
/// </summary>
/// <typeparam name="T">Type of the object pool.</typeparam>
public class ObjectPool<T> : IDisposable, IObjectPool<T> where T : class
{
internal readonly Stack<T> m_Stack;
readonly Func<T> m_CreateFunc;
readonly Action<T> m_ActionOnGet;
readonly Action<T> m_ActionOnRelease;
readonly Action<T> m_ActionOnDestroy;
readonly int m_MaxSize; // Used to prevent catastrophic memory retention.
internal bool m_CollectionCheck;
/// <summary>
/// The total number of active and inactive objects.
/// </summary>
public int CountAll { get; private set; }
/// <summary>
/// Number of objects that have been created by the pool but are currently in use and have not yet been returned.
/// </summary>
public int CountActive { get { return CountAll - CountInactive; } }
/// <summary>
/// Number of objects that are currently available in the pool.
/// </summary>
public int CountInactive { get { return m_Stack.Count; } }
/// <summary>
/// Creates a new ObjectPool.
/// </summary>
/// <param name="createFunc">Use to create a new instance when the pool is empty. In most cases this will just be <code>() => new T()</code></param>
/// <param name="actionOnGet">Called when the instance is being taken from the pool.</param>
/// <param name="actionOnRelease">Called when the instance is being returned to the pool. This could be used to clean up or disable the instance.</param>
/// <param name="actionOnDestroy">Called when the element can not be returned to the pool due to it being equal to the maxSize.</param>
/// <param name="collectionCheck">Collection checks are performed when an instance is returned back to the pool. An exception will be thrown if the instance is already in the pool. Collection checks are only performed in the Editor.</param>
/// <param name="defaultCapacity">The default capacity the stack will be created with.</param>
/// <param name="maxSize">The maximum size of the pool. When the pool reaches the max size then any further instances returned to the pool will be ignored and can be garbage collected. This can be used to prevent the pool growing to a very large size.</param>
public ObjectPool(Func<T> createFunc, Action<T> actionOnGet = null, Action<T> actionOnRelease = null, Action<T> actionOnDestroy = null, bool collectionCheck = true, int defaultCapacity = 10, int maxSize = 10000)
{
if (createFunc == null)
throw new ArgumentNullException(nameof(createFunc));
if (maxSize <= 0)
throw new ArgumentException("Max Size must be greater than 0", nameof(maxSize));
m_Stack = new Stack<T>(defaultCapacity);
m_CreateFunc = createFunc;
m_MaxSize = maxSize;
m_ActionOnGet = actionOnGet;
m_ActionOnRelease = actionOnRelease;
m_ActionOnDestroy = actionOnDestroy;
m_CollectionCheck = collectionCheck;
}
/// <summary>
/// Get an object from the pool.
/// </summary>
/// <returns>A new object from the pool.</returns>
public T Get()
{
T element;
if (m_Stack.Count == 0)
{
element = m_CreateFunc();
CountAll++;
}
else
{
element = m_Stack.Pop();
}
m_ActionOnGet?.Invoke(element);
return element;
}
/// <summary>
/// Get a new <see cref="PooledObject"/> which can be used to return the instance back to the pool when the PooledObject is disposed.
/// </summary>
/// <param name="v">Output new typed object.</param>
/// <returns>New PooledObject</returns>
public PooledObject<T> Get(out T v) => new PooledObject<T>(v = Get(), this);
/// <summary>
/// Release an object to the pool.
/// </summary>
/// <param name="element">Object to release.</param>
public void Release(T element)
{
if (m_CollectionCheck && m_Stack.Count > 0)
{
if (m_Stack.Contains(element))
throw new InvalidOperationException("Trying to release an object that has already been released to the pool.");
}
m_ActionOnRelease?.Invoke(element);
if (CountInactive < m_MaxSize)
{
m_Stack.Push(element);
}
else
{
m_ActionOnDestroy?.Invoke(element);
}
}
/// <summary>
/// Releases all pooled objects so they can be garbage collected.
/// </summary>
public void Clear()
{
if (m_ActionOnDestroy != null)
{
foreach (var item in m_Stack)
{
m_ActionOnDestroy(item);
}
}
m_Stack.Clear();
CountAll = 0;
}
public void Dispose()
{
// Ensure we do a clear so the destroy action can be called.
Clear();
}
}
}