Mercurial > pub > ImplabNet
view Implab/ObjectPool.cs @ 138:f75cfa58e3d4 v2
added ICancellable.Cancel(Exception) to allow specify the reason of cancellation
author | cin |
---|---|
date | Tue, 17 Feb 2015 18:16:26 +0300 |
parents | 2573b562e328 |
children |
line wrap: on
line source
using Implab.Parallels; using System; using System.Threading; namespace Implab { /// <summary> /// Базовый класс для создания пулов объектов. /// </summary> /// <remarks> /// <para>Пул объектов позволяет многократно использовать один и тотже объект, /// что актуально для объектов, создание которых требует существенных ресурсов. /// Пул объектов использует слабые ссылки, чтобы не препятствовать освобождению /// ресурсов и создает новые объекты при необходимости.</para> /// <para> /// Наследники должны реализовывать метод <see cref="CreateInstance()"/> для создания /// новых экземпляров. /// </para> /// <para>Пул поддерживает обращения сразу из нескольких потоков.</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,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)); } } } }