Mercurial > pub > ImplabNet
view Implab/Components/ObjectPool.cs @ 259:7d52dc684bbd v3
PollingComponent: implemented correct stopping
author | cin |
---|---|
date | Fri, 13 Apr 2018 03:57:39 +0300 |
parents | 7c7e9ad6fe4a |
children |
line wrap: on
line source
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)); } } } }