|
|
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 MTQueue<T> m_queue = new MTQueue<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
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|