using Implab.Parallels;
using System;
using System.Threading;
namespace Implab {
///
/// Базовый класс для создания пулов объектов.
///
///
/// Пул объектов позволяет многократно использовать один и тотже объект,
/// что актуально для объектов, создание которых требует существенных ресурсов.
/// Пул объектов использует слабые ссылки, чтобы не препятствовать освобождению
/// ресурсов и создает новые объекты при необходимости.
///
/// Наследники должны реализовывать метод для создания
/// новых экземпляров.
///
/// Пул поддерживает обращения сразу из нескольких потоков.
///
public abstract class ObjectPool where T : class {
readonly MTQueue m_queue = new MTQueue();
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));
}
}
}
}