-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathObjectPool.cs
More file actions
184 lines (160 loc) · 5.92 KB
/
ObjectPool.cs
File metadata and controls
184 lines (160 loc) · 5.92 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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Copyright (C) SomaSim LLC.
// Open source software. Please see LICENSE file for details.
using System;
using System.Collections.Generic;
namespace SomaSim.Util
{
/// <summary>
/// Interface for objects managed by an object pool.
/// </summary>
public interface IObjectPoolElement
{
/// <summary>
/// This function should be implemented by any object pool entries, and it should
/// release any resources used by this entry, and null out any references
/// that this instance is holding.
/// </summary>
void Reset ();
}
/// <summary>
/// Object pool manages a number of entires, which can be reused instead of
/// getting garbage collected.
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObjectPool<T> where T : class, IObjectPoolElement, new()
{
/// <summary>
/// Function that generates instances of IObjectPoolElement
/// </summary>
private Func<T> _factory;
/// <summary>
/// List of all entries returned from circulation, and ready for reuse.
/// </summary>
private Stack<T> _free;
/// <summary>
/// Number of elements currently in circulation, that haven't been returned.
/// </summary>
private int _usedcount;
public int UsedListSize => _usedcount;
public int FreeListSize => _free != null ? _free.Count : -1;
/// <summary>
/// Initializes the object pool.
/// </summary>
public void Initialize () => Initialize(() => new T());
/// <summary>
/// Initializes the object pool with a specific factory for new elements
/// (the factory can initialize the elements in a specific way, for example)
/// </summary>
/// <param name="factory"></param>
public void Initialize (Func<T> factory) {
_factory = factory;
_free = new Stack<T>();
}
/// <summary>
/// Releases all elements and resources held by this pool.
/// </summary>
public void Release () {
_free.Clear();
_free = null;
_factory = null;
}
/// <summary>
/// Allocates a new object from the pool, either by pulling from the free list, or
/// by calling the factory function to generate a brand new instance.
/// </summary>
/// <returns></returns>
public T Allocate () {
T element = (_free.Count > 0) ? _free.Pop() : _factory.Invoke();
_usedcount++;
return element;
}
/// <summary>
/// Returns the element back to the pool, and resets its data.
/// </summary>
/// <param name="element"></param>
public void Free (T element) {
element.Reset();
_usedcount--;
_free.Push(element);
}
}
/// <summary>
/// Object pool manages a number of entires, which can be reused instead of
/// getting garbage collected.
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObjectPoolResettable<T>
{
/// <summary>
/// Function that generates instances of T
/// </summary>
private Func<T> _factoryFn;
/// <summary>
/// Function that activates an instance of T after it's been allocated (new or reused). Optional.
/// </summary>
private Action<T> _activateFn;
/// <summary>
/// Function that resets the instance of T after it's been free'd.
/// </summary>
private Action<T> _resetFn;
/// <summary>
/// Function that destroys a freed instance of T when shutting down
/// </summary>
private Action<T> _destroyFn;
/// <summary>
/// List of all entries returned from circulation, and ready for reuse.
/// </summary>
private List<T> _free;
/// <summary>
/// Number of elements currently in circulation, that haven't been returned.
/// </summary>
private int _usedcount;
public int UsedListSize => _usedcount;
public int FreeListSize => _free != null ? _free.Count : -1;
/// <summary>
/// Initializes the object pool with a specific factory for new elements
/// (the factory can initialize the elements in a specific way, for example)
/// and a reset function that will be called on each free'd element.
/// </summary>
/// <param name="factory"></param>
public void Initialize (Func<T> factory, Action<T> activate, Action<T> reset, Action<T> destroy) {
_factoryFn = factory;
_activateFn = activate;
_resetFn = reset;
_destroyFn = destroy;
_free = new List<T>();
}
/// <summary>
/// Releases all elements and resources held by this pool.
/// </summary>
public void Release () {
while (_free.Count > 0) {
_destroyFn(_free.RemoveLast());
}
_free = null;
_destroyFn = null;
_activateFn = null;
_factoryFn = null;
}
/// <summary>
/// Allocates a new object from the pool, either by pulling from the free list, or
/// by calling the factory function to generate a brand new instance.
/// </summary>
/// <returns></returns>
public T Allocate () {
T element = (_free.Count > 0) ? _free.RemoveLast() : _factoryFn.Invoke();
_usedcount++;
_activateFn?.Invoke(element);
return element;
}
/// <summary>
/// Returns the element back to the pool, and resets its data.
/// </summary>
/// <param name="element"></param>
public void Free (T element) {
_resetFn?.Invoke(element);
_usedcount--;
_free.Add(element);
}
}
}