summaryrefslogtreecommitdiff
path: root/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Core/Pooling/ObjectPool.cs
blob: 262830cc61973d1aabdb9b53b85f63e42d9faf25 (plain)
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
#if !UNITY_EDITOR
// Extra optimizations when not running in the editor, but less error checking
#define ASTAR_OPTIMIZE_POOLING
#endif

using System;
using System.Collections.Generic;

namespace Pathfinding.Util {
	public interface IAstarPooledObject {
		void OnEnterPool();
	}

	/// <summary>
	/// Lightweight object Pool for IAstarPooledObject.
	/// Handy class for pooling objects of type T which implements the IAstarPooledObject interface.
	///
	/// Usage:
	/// - Claim a new object using <code> SomeClass foo = ObjectPool<SomeClass>.Claim (); </code>
	/// - Use it and do stuff with it
	/// - Release it with <code> ObjectPool<SomeClass>.Release (foo); </code>
	///
	/// After you have released a object, you should never use it again.
	///
	/// Since: Version 3.2
	/// Version: Since 3.7.6 this class is thread safe
	/// See: Pathfinding.Util.ListPool
	/// See: ObjectPoolSimple
	/// </summary>
	public static class ObjectPool<T> where T : class, IAstarPooledObject, new(){
		public static T Claim () {
			return ObjectPoolSimple<T>.Claim();
		}

		public static void Release (ref T obj) {
			obj.OnEnterPool();
			ObjectPoolSimple<T>.Release(ref obj);
		}
	}

	/// <summary>
	/// Lightweight object Pool.
	/// Handy class for pooling objects of type T.
	///
	/// Usage:
	/// - Claim a new object using <code> SomeClass foo = ObjectPool<SomeClass>.Claim (); </code>
	/// - Use it and do stuff with it
	/// - Release it with <code> ObjectPool<SomeClass>.Release (foo); </code>
	///
	/// After you have released a object, you should never use it again.
	///
	/// Since: Version 3.2
	/// Version: Since 3.7.6 this class is thread safe
	/// See: Pathfinding.Util.ListPool
	/// See: ObjectPool
	/// </summary>
	public static class ObjectPoolSimple<T> where T : class, new(){
		/// <summary>Internal pool</summary>
		static List<T> pool = new List<T>();

#if !ASTAR_NO_POOLING
		static readonly HashSet<T> inPool = new HashSet<T>();
#endif

		/// <summary>
		/// Claim a object.
		/// Returns a pooled object if any are in the pool.
		/// Otherwise it creates a new one.
		/// After usage, this object should be released using the Release function (though not strictly necessary).
		/// </summary>
		public static T Claim () {
#if ASTAR_NO_POOLING
			return new T();
#else
			lock (pool) {
				if (pool.Count > 0) {
					T ls = pool[pool.Count-1];
					pool.RemoveAt(pool.Count-1);
					inPool.Remove(ls);
					return ls;
				} else {
					return new T();
				}
			}
#endif
		}

		/// <summary>
		/// Releases an object.
		/// After the object has been released it should not be used anymore.
		/// The variable will be set to null to prevent silly mistakes.
		///
		/// Throws: System.InvalidOperationException
		/// Releasing an object when it has already been released will cause an exception to be thrown.
		/// However enabling ASTAR_OPTIMIZE_POOLING will prevent this check.
		///
		/// See: Claim
		/// </summary>
		public static void Release (ref T obj) {
#if !ASTAR_NO_POOLING
			lock (pool) {
#if !ASTAR_OPTIMIZE_POOLING
				if (!inPool.Add(obj)) {
					throw new InvalidOperationException("You are trying to pool an object twice. Please make sure that you only pool it once.");
				}
#endif
				pool.Add(obj);
			}
#endif
			obj = null;
		}

		/// <summary>
		/// Clears the pool for objects of this type.
		/// This is an O(n) operation, where n is the number of pooled objects.
		/// </summary>
		public static void Clear () {
			lock (pool) {
#if !ASTAR_OPTIMIZE_POOLING && !ASTAR_NO_POOLING
				inPool.Clear();
#endif
				pool.Clear();
			}
		}

		/// <summary>Number of objects of this type in the pool</summary>
		public static int GetSize () {
			return pool.Count;
		}
	}
}