152
|
1 using Implab.Parallels;
|
|
2 using System;
|
|
3 using System.Threading;
|
|
4
|
|
5 namespace Implab.Components {
|
|
6 /// <summary>
|
154
|
7 /// The base class for creating object pools.
|
152
|
8 /// </summary>
|
|
9 /// <remarks>
|
154
|
10 /// <para>The objects pool is offers frequently requested objects to be reused, this gives
|
|
11 /// a gool speed improvement for the 'heavy' objects. To avoid memory overhead the pool uses
|
|
12 /// weak references allowing CG to do it's work. If there are no free objects in the pool
|
|
13 /// they are created on demand. </para>
|
152
|
14 /// <para>
|
154
|
15 /// Implementors need to defined a <see cref="CreateInstance()"/> method
|
152
|
16 /// </para>
|
154
|
17 /// <para>The instances of this class are thred-safe.</para>
|
152
|
18 /// </remarks>
|
|
19 public abstract class ObjectPool<T> where T : class {
|
|
20 readonly AsyncQueue<WeakReference> m_queue = new AsyncQueue<WeakReference>();
|
|
21 readonly int m_size;
|
|
22 int m_count = 0;
|
|
23
|
|
24 protected ObjectPool() : this(Environment.ProcessorCount+1) {
|
|
25
|
|
26 }
|
|
27
|
|
28 protected ObjectPool(int size) {
|
251
|
29 Safe.ArgumentInRange(size > 0, nameof(size));
|
152
|
30
|
|
31 m_size = size;
|
|
32 }
|
|
33
|
154
|
34 /// <summary>
|
|
35 /// Creates the instance if there are no free ones in the pool.
|
|
36 /// </summary>
|
|
37 /// <returns>The new instance.</returns>
|
152
|
38 protected abstract T CreateInstance();
|
|
39
|
154
|
40 /// <summary>
|
|
41 /// Cleanups the instance.
|
|
42 /// </summary>
|
|
43 /// <param name="instance">The instance to cleanup and prepare it for the next use.</param>
|
152
|
44 protected virtual void CleanupInstance(T instance) {
|
|
45 }
|
|
46
|
154
|
47 /// <summary>
|
|
48 /// Allocate free instance from the pool or reates a new one.
|
|
49 /// </summary>
|
152
|
50 public T Allocate() {
|
|
51 WeakReference reference;
|
|
52 while (m_queue.TryDequeue(out reference)) {
|
|
53 Interlocked.Decrement(ref m_count);
|
|
54 object instance = reference.Target;
|
|
55 if (instance == null)
|
|
56 continue;
|
|
57 return (T)instance;
|
|
58 }
|
|
59 return CreateInstance();
|
|
60 }
|
|
61
|
154
|
62 /// <summary>
|
|
63 /// Release the specified instance and returns it to the pool of free instances.
|
|
64 /// </summary>
|
|
65 /// <param name="instance">The instance to return to the pool.</param>
|
|
66 /// <remarks>Before the instance is returned to the pool the <see cref="CleanupInstance(T)"/> is called.</remarks>
|
152
|
67 public void Release(T instance) {
|
|
68 if (m_count < m_size && instance != null) {
|
|
69 Interlocked.Increment(ref m_count);
|
|
70 CleanupInstance(instance);
|
|
71 m_queue.Enqueue(new WeakReference(instance));
|
|
72 }
|
|
73 }
|
|
74 }
|
|
75 }
|