diff --git a/Implab/Disposable.cs b/Implab/Disposable.cs --- a/Implab/Disposable.cs +++ b/Implab/Disposable.cs @@ -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 { /// @@ -11,40 +9,84 @@ namespace Implab { /// 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; + } } + /// + /// Asserts the object is not disposed. + /// + /// The object is disposed + /// + /// Успешная проверка того, что объект не освобожден еще не гарантирует, что он не + /// будет освобожден сразу после нее, поэтому методы использующие проверку должны + /// учитывать, что объект может быть освобожден из параллельного потока. + /// Данны метод служит для упрощения отладки ошибок при использовании объекта после его + /// освобождения. + /// + /// + /// // пример синхронизированного освобождения ресурсов + /// 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); + /// } + /// } + /// protected void AssertNotDisposed() { - if (m_disposed) - throw new ObjectDisposedException(this.ToString()); + Thread.MemoryBarrier(); + if (m_disposed != 0) + throw new ObjectDisposedException(ToString()); } /// - /// Переводит объект в состояние Disposed и вызывает событие + /// Вызывает событие /// /// Признак того, что нужно освободить ресурсы, иначе данный метод /// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого /// объекта. /// - /// Данный метод осуществляет проверку того, что объект уже был освобожден, чтобы не вызывать - /// событие . Не поддерживает многопоточность. + /// Данный метод вызывается гарантированно один раз даже при одновременном вызове + /// из нескольких потоков. /// 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); + } } ///