# HG changeset patch # User cin # Date 1415194796 -10800 # Node ID 673947ce458a94e072967b0525301540a7a73a56 # Parent 8ddf1648eca4624d0d2a4e6ea23e0a94793e2d35 added multithreading support to Disposable class diff -r 8ddf1648eca4 -r 673947ce458a Implab/Disposable.cs --- 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 { /// @@ -11,40 +9,84 @@ /// 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); + } } ///