/
ObjectPool.cs
52 lines (43 loc) · 1.64 KB
/
ObjectPool.cs
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
/*
* Copyright Lamont Granquist (lamont@scriptkiddie.org)
* Dual licensed under the MIT (MIT-LICENSE) license
* and GPLv2 (GPLv2-LICENSE) license or any later version.
*/
#nullable enable
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace MechJebLib.Utils
{
public class ObjectPoolBase
{
// The object pool is global state, and global state is horrible for unit tests, so by setting
// UseGlobal = false the tests will use per-thread object pools, which keeps them from scribbling
// over each other's objectpools. This lets me write tests to check for allocations to make sure
// that the use of the threadpool isn't leaking objects on successive invocations.
internal static bool UseGlobal = true;
}
// TODO: min and max object levels
public class ObjectPool<T> : ObjectPoolBase
{
private readonly Func<T> _create;
private readonly Action<T> _reset;
private readonly ConcurrentBag<T> _globalPool = new ConcurrentBag<T>();
private static readonly ThreadLocal<ConcurrentBag<T>> _localPool = new ThreadLocal<ConcurrentBag<T>>(() => new ConcurrentBag<T>());
private ConcurrentBag<T> _pool => UseGlobal ? _globalPool : _localPool.Value;
public ObjectPool(Func<T> create, Action<T> reset)
{
_reset = reset;
_create = create;
}
public T Borrow()
{
return _pool.TryTake(out T item) ? item : _create();
}
public void Release(T item)
{
_reset(item);
_pool.Add(item);
}
}
}