ObjectPool.cs
75 lines
| 2.7 KiB
| text/x-csharp
|
CSharpLexer
|
|
r152 | using Implab.Parallels; | ||
| using System; | ||||
| using System.Threading; | ||||
| namespace Implab.Components { | ||||
| /// <summary> | ||||
|
|
r154 | /// The base class for creating object pools. | ||
|
|
r152 | /// </summary> | ||
| /// <remarks> | ||||
|
|
r154 | /// <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> | ||||
|
|
r152 | /// <para> | ||
|
|
r154 | /// Implementors need to defined a <see cref="CreateInstance()"/> method | ||
|
|
r152 | /// </para> | ||
|
|
r154 | /// <para>The instances of this class are thred-safe.</para> | ||
|
|
r152 | /// </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,1,size,"size"); | ||||
| m_size = size; | ||||
| } | ||||
|
|
r154 | /// <summary> | ||
| /// Creates the instance if there are no free ones in the pool. | ||||
| /// </summary> | ||||
| /// <returns>The new instance.</returns> | ||||
|
|
r152 | protected abstract T CreateInstance(); | ||
|
|
r154 | /// <summary> | ||
| /// Cleanups the instance. | ||||
| /// </summary> | ||||
| /// <param name="instance">The instance to cleanup and prepare it for the next use.</param> | ||||
|
|
r152 | protected virtual void CleanupInstance(T instance) { | ||
| } | ||||
|
|
r154 | /// <summary> | ||
| /// Allocate free instance from the pool or reates a new one. | ||||
| /// </summary> | ||||
|
|
r152 | 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(); | ||||
| } | ||||
|
|
r154 | /// <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> | ||||
|
|
r152 | 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)); | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
