##// END OF EJS Templates
fixed object pool
fixed object pool

File last commit:

r83:397fe8db0806 v2
r83:397fe8db0806 v2
Show More
ObjectPool.cs
92 lines | 3.1 KiB | text/x-csharp | CSharpLexer
using System;
using Implab.Parallels;
using System.Threading;
namespace Implab {
public class ObjectPool<T> : IDisposable {
readonly Func<T> m_factory;
readonly Action<T> m_cleanup;
readonly int m_size;
readonly MTQueue<T> m_queue = new MTQueue<T>();
bool m_disposed;
int m_count;
public ObjectPool(Func<T> factory, Action<T> cleanup, int size) {
Safe.ArgumentNotNull(factory, "factory");
Safe.ArgumentInRange(size, 1, size, "size");
m_factory = factory;
m_cleanup = cleanup;
m_size = size;
}
public ObjectPool(Func<T> factory, Action<T> cleanup) : this(factory,cleanup,Environment.ProcessorCount+1) {
}
public ObjectPool(Func<T> factory) : this(factory,null,Environment.ProcessorCount+1) {
}
public ObjectPoolWrapper<T> AllocateAuto() {
return new ObjectPoolWrapper<T>(Allocate(), this);
}
public T Allocate() {
if (m_disposed)
throw new ObjectDisposedException(this.ToString());
T instance;
if (m_queue.TryDequeue(out instance)) {
Interlocked.Decrement(ref m_count);
} else {
instance = m_factory();
}
return instance;
}
public void Release(T instance) {
Thread.MemoryBarrier();
if (m_count < m_size && !m_disposed) {
Interlocked.Increment(ref m_count);
if (m_cleanup != null)
m_cleanup(instance);
m_queue.Enqueue(instance);
// пока элемент возвращался в кеш, была начата операция освобождения всего кеша
// и возможно уже законцена, в таком случае следует извлечь элемент обратно и
// освободить его. Если операция освобождения кеша еще не заврешилась, то будет
// изъят и освобожден произвольный элемен, что не повлияет на ход всего процесса.
if (m_disposed && m_queue.TryDequeue(out instance) && instance is IDisposable)
((IDisposable)instance).Dispose() ;
} else {
if (instance is IDisposable)
((IDisposable)instance).Dispose();
}
}
protected virtual void Dispose(bool disposing) {
if (disposing) {
m_disposed = true;
T instance;
while (m_queue.TryDequeue(out instance))
if (instance is IDisposable)
((IDisposable)instance).Dispose();
}
}
#region IDisposable implementation
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}