ObjectPool.cs
60 lines
| 2.3 KiB
| text/x-csharp
|
CSharpLexer
/ Implab / ObjectPool.cs
cin
|
r117 | 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 MTQueue<WeakReference> m_queue = new MTQueue<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)); | ||||
} | ||||
} | ||||
} | ||||
} | ||||