ObjectPool.cs
85 lines
| 2.8 KiB
| text/x-csharp
|
CSharpLexer
/ Implab / ObjectPool.cs
cin
|
r82 | 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>(); | ||||
volatile bool m_disposed; | ||||
volatile 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> Allocate() { | ||||
if (m_disposed) | ||||
throw new ObjectDisposedException(this.ToString()); | ||||
T instance; | ||||
if (m_queue.TryDequeue(out instance)) { | ||||
Interlocked.Decrement(ref m_count); | ||||
return instance; | ||||
} else { | ||||
instance = m_factory(); | ||||
} | ||||
return new ObjectPoolWrapper<T>(instance, this); | ||||
} | ||||
public void Release(T instance) { | ||||
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)) | ||||
Safe.Dispose(instance); | ||||
} else { | ||||
Safe.Dispose(instance); | ||||
} | ||||
} | ||||
protected virtual void Dispose(bool disposing) { | ||||
if (disposing) { | ||||
m_disposed = true; | ||||
T instance; | ||||
while (m_queue.TryDequeue(out instance)) | ||||
Safe.Dispose(instance); | ||||
} | ||||
} | ||||
#region IDisposable implementation | ||||
public void Dispose() { | ||||
Dispose(true); | ||||
GC.SuppressFinalize(this); | ||||
} | ||||
#endregion | ||||
} | ||||
} | ||||