##// END OF EJS Templates
minor changes
minor changes

File last commit:

r119:2573b562e328 v2
r146:e03ccec4a08d v2
Show More
DisposablePool.cs
90 lines | 3.0 KiB | text/x-csharp | CSharpLexer
using System;
using Implab.Parallels;
using System.Threading;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
namespace Implab {
public abstract class DisposablePool<T> : IDisposable {
readonly int m_size;
readonly AsyncQueue<T> m_queue = new AsyncQueue<T>();
[SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
static readonly bool _isValueType = typeof(T).IsValueType;
bool m_disposed;
int m_count;
protected DisposablePool(int size) {
m_size = size;
}
protected DisposablePool() : this(Environment.ProcessorCount+1) {
}
public T Allocate() {
if (m_disposed)
throw new ObjectDisposedException(ToString());
T instance;
if (m_queue.TryDequeue(out instance)) {
Interlocked.Decrement(ref m_count);
} else {
instance = CreateInstance();
Debug.Assert(!Object.Equals(instance, default(T)) || _isValueType);
}
return instance;
}
protected abstract T CreateInstance();
protected virtual void CleanupInstance(T instance) {
}
public void Release(T instance) {
if ( Object.Equals(instance,default(T)) && !_isValueType)
return;
Thread.MemoryBarrier();
if (m_count < m_size && !m_disposed) {
Interlocked.Increment(ref m_count);
CleanupInstance(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
}
}