using Implab.Parallels; using System; using System.Threading; namespace Implab.Components { /// /// The base class for creating object pools. /// /// /// 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. /// /// Implementors need to defined a method /// /// The instances of this class are thred-safe. /// public abstract class ObjectPool where T : class { readonly AsyncQueue m_queue = new AsyncQueue(); 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; } /// /// Creates the instance if there are no free ones in the pool. /// /// The new instance. protected abstract T CreateInstance(); /// /// Cleanups the instance. /// /// The instance to cleanup and prepare it for the next use. protected virtual void CleanupInstance(T instance) { } /// /// Allocate free instance from the pool or reates a new one. /// 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(); } /// /// Release the specified instance and returns it to the pool of free instances. /// /// The instance to return to the pool. /// Before the instance is returned to the pool the is called. 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)); } } } }