Mercurial > pub > ImplabNet
changeset 100:673947ce458a v2
added multithreading support to Disposable class
author | cin |
---|---|
date | Wed, 05 Nov 2014 16:39:56 +0300 |
parents | 8ddf1648eca4 |
children | 279e226dffdd |
files | Implab/Disposable.cs |
diffstat | 1 files changed, 60 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/Implab/Disposable.cs Wed Nov 05 02:31:35 2014 +0300 +++ b/Implab/Disposable.cs Wed Nov 05 16:39:56 2014 +0300 @@ -1,9 +1,7 @@ using Implab.Diagnostics; using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Web; +using System.Threading; +using System.IO; namespace Implab { /// <summary> @@ -11,40 +9,84 @@ /// </summary> public class Disposable : IDisposable { - bool m_disposed; + int m_disposed; public event EventHandler Disposed; public bool IsDisposed { - get { return m_disposed; } + get { + Thread.MemoryBarrier(); + return m_disposed != 0; + } } + /// <summary> + /// Asserts the object is not disposed. + /// </summary> + /// <exception cref="ObjectDisposedException">The object is disposed</exception> + /// <remarks> + /// Успешная проверка того, что объект не освобожден еще не гарантирует, что он не + /// будет освобожден сразу после нее, поэтому методы использующие проверку должны + /// учитывать, что объект может быть освобожден из параллельного потока. + /// Данны метод служит для упрощения отладки ошибок при использовании объекта после его + /// освобождения. + /// </remarks> + /// <example> + /// // пример синхронизированного освобождения ресурсов + /// class FileStore : Disposable { + /// readonly TextWriter m_file; + /// readonly obejct m_sync = new object(); + /// + /// public FileStore(string file) { + /// m_file = new TextWriter(File.OpenWrite(file)); + /// } + /// + /// public void Write(string text) { + /// lock(m_sync) { + /// AssertNotDisposed(); + /// m_file.Write(text); + /// } + /// } + /// + /// protected override void Dispose(bool disposing) { + /// if (disposing) + /// lock(m_sync) { + /// m_file.Dipose(); + /// base.Dispose(true); + /// } + /// else + /// base.Dispose(false); + /// } + /// } + /// <example> protected void AssertNotDisposed() { - if (m_disposed) - throw new ObjectDisposedException(this.ToString()); + Thread.MemoryBarrier(); + if (m_disposed != 0) + throw new ObjectDisposedException(ToString()); } /// <summary> - /// Переводит объект в состояние <c>Disposed</c> и вызывает событие <see cref="Disposed"/> + /// Вызывает событие <see cref="Disposed"/> /// </summary> /// <param name="disposing">Признак того, что нужно освободить ресурсы, иначе данный метод /// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого /// объекта.</param> /// <remarks> - /// Данный метод осуществляет проверку того, что объект уже был освобожден, чтобы не вызывать - /// событие <see cref="Disposed"/>. Не поддерживает многопоточность. + /// Данный метод вызывается гарантированно один раз даже при одновременном вызове <see cref="Dispose()"/> + /// из нескольких потоков. /// </remarks> protected virtual void Dispose(bool disposing) { - if (disposing && !m_disposed) { - m_disposed = true; - + if (disposing) { EventHandler temp = Disposed; - if (temp != null) - temp(this,EventArgs.Empty); + if (temp != null) + temp(this, EventArgs.Empty); } } + public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); + if (Interlocked.Increment(ref m_disposed) == 1) { + Dispose(true); + GC.SuppressFinalize(this); + } } /// <summary>