using Implab.Parallels; using System; using System.Threading; namespace Implab.Components { /// /// Базовый класс для создания пулов объектов. /// /// /// Пул объектов позволяет многократно использовать один и тотже объект, /// что актуально для объектов, создание которых требует существенных ресурсов. /// Пул объектов использует слабые ссылки, чтобы не препятствовать освобождению /// ресурсов и создает новые объекты при необходимости. /// /// Наследники должны реализовывать метод для создания /// новых экземпляров. /// /// Пул поддерживает обращения сразу из нескольких потоков. /// 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; } protected abstract T CreateInstance(); protected virtual void CleanupInstance(T instance) { } 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(); } 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)); } } } }