##// END OF EJS Templates
Implab.Diagnostics drafts
Implab.Diagnostics drafts

File last commit:

r251:7c7e9ad6fe4a v3
r253:34df34841225 v3.0.1-beta v3
Show More
ObjectPool.cs
75 lines | 2.7 KiB | text/x-csharp | CSharpLexer
using Implab.Parallels;
using System;
using System.Threading;
namespace Implab.Components {
/// <summary>
/// The base class for creating object pools.
/// </summary>
/// <remarks>
/// <para>The objects pool is offers frequently requested objects to be reused, this gives
/// a gool speed improvement for the 'heavy' objects. To avoid memory overhead the pool uses
/// weak references allowing CG to do it's work. If there are no free objects in the pool
/// they are created on demand. </para>
/// <para>
/// Implementors need to defined a <see cref="CreateInstance()"/> method
/// </para>
/// <para>The instances of this class are thred-safe.</para>
/// </remarks>
public abstract class ObjectPool<T> where T : class {
readonly AsyncQueue<WeakReference> m_queue = new AsyncQueue<WeakReference>();
readonly int m_size;
int m_count = 0;
protected ObjectPool() : this(Environment.ProcessorCount+1) {
}
protected ObjectPool(int size) {
Safe.ArgumentInRange(size > 0, nameof(size));
m_size = size;
}
/// <summary>
/// Creates the instance if there are no free ones in the pool.
/// </summary>
/// <returns>The new instance.</returns>
protected abstract T CreateInstance();
/// <summary>
/// Cleanups the instance.
/// </summary>
/// <param name="instance">The instance to cleanup and prepare it for the next use.</param>
protected virtual void CleanupInstance(T instance) {
}
/// <summary>
/// Allocate free instance from the pool or reates a new one.
/// </summary>
public T Allocate() {
WeakReference reference;
while (m_queue.TryDequeue(out reference)) {
Interlocked.Decrement(ref m_count);
object instance = reference.Target;
if (instance == null)
continue;
return (T)instance;
}
return CreateInstance();
}
/// <summary>
/// Release the specified instance and returns it to the pool of free instances.
/// </summary>
/// <param name="instance">The instance to return to the pool.</param>
/// <remarks>Before the instance is returned to the pool the <see cref="CleanupInstance(T)"/> is called.</remarks>
public void Release(T instance) {
if (m_count < m_size && instance != null) {
Interlocked.Increment(ref m_count);
CleanupInstance(instance);
m_queue.Enqueue(new WeakReference(instance));
}
}
}
}