diff --git a/Implab/Implab.csproj b/Implab/Implab.csproj --- a/Implab/Implab.csproj +++ b/Implab/Implab.csproj @@ -7,8 +7,6 @@ Library Implab Implab - 8.0.30703 - 2.0 true @@ -123,8 +121,8 @@ - - + + diff --git a/Implab/ObjectPool.cs b/Implab/ObjectPool.cs new file mode 100644 --- /dev/null +++ b/Implab/ObjectPool.cs @@ -0,0 +1,85 @@ +using System; +using Implab.Parallels; +using System.Threading; + +namespace Implab { + public class ObjectPool : IDisposable { + readonly Func m_factory; + readonly Action m_cleanup; + readonly int m_size; + readonly MTQueue m_queue = new MTQueue(); + + volatile bool m_disposed; + + volatile int m_count; + + public ObjectPool(Func factory, Action 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 factory, Action cleanup) : this(factory,cleanup,Environment.ProcessorCount+1) { + } + + public ObjectPool(Func factory) : this(factory,null,Environment.ProcessorCount+1) { + } + + public ObjectPoolWrapper 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(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 + } +} + diff --git a/Implab/ObjectPoolWrapper.cs b/Implab/ObjectPoolWrapper.cs new file mode 100644 --- /dev/null +++ b/Implab/ObjectPoolWrapper.cs @@ -0,0 +1,24 @@ +using System; + +namespace Implab { + public struct ObjectPoolWrapper : IDisposable { + readonly T m_value; + readonly ObjectPool m_pool; + + internal ObjectPoolWrapper(T value, ObjectPool pool) { + m_value = value; + m_pool = pool; + } + + public T Value { + get { return m_value; } + } + + #region IDisposable implementation + public void Dispose() { + m_pool.Release(m_value); + } + #endregion + } +} + diff --git a/Implab/SyncPool.cs b/Implab/SyncPool.cs deleted file mode 100644 --- a/Implab/SyncPool.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using Implab.Parallels; -using System.Threading; - -namespace Implab { - /*public class SyncPool : IDisposable { - readonly Func m_factory; - readonly Action m_cleanup; - readonly int m_size; - readonly MTQueue m_queue = new MTQueue(); - - volatile bool m_disposed; - - volatile int m_count; - - public SyncPool(Func factory, Action cleanup, int size) { - Safe.ArgumentNotNull(factory, "factory"); - Safe.ArgumentInRange(size, 1, size, "size"); - - m_factory = factory; - m_cleanup = cleanup; - m_size = size; - } - - public SyncPool(Func factory, Action cleanup) : this(factory,cleanup,Environment.ProcessorCount+1) { - } - - public SyncPool(Func factory) : this(factory,null,Environment.ProcessorCount+1) { - } - - public SyncPoolWrapper 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 SyncPoolWrapper(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 - }*/ -} - diff --git a/Implab/SyncPoolWrapper.cs b/Implab/SyncPoolWrapper.cs deleted file mode 100644 --- a/Implab/SyncPoolWrapper.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace Implab { - /*public struct SyncPoolWrapper : IDisposable { - readonly T m_value; - readonly SyncPool m_pool; - - internal SyncPoolWrapper(T value, SyncPool pool) { - m_value = value; - m_pool = pool; - } - - public T Value { - get { return m_value; } - } - - #region IDisposable implementation - public void Dispose() { - m_pool.Release(m_value); - } - #endregion - }*/ -} -