Mercurial > pub > ImplabNet
diff Implab/Components/Disposable.cs @ 152:240aa6994018 v2
component model refactoring
author | cin |
---|---|
date | Thu, 11 Feb 2016 01:56:27 +0300 |
parents | |
children | 7d07503621fe |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Components/Disposable.cs Thu Feb 11 01:56:27 2016 +0300 @@ -0,0 +1,103 @@ +using Implab.Diagnostics; +using System; +using System.Threading; + +namespace Implab.Components { + /// <summary> + /// Base class the objects which support disposing. + /// </summary> + public class Disposable : IDisposable { + + int m_disposed; + + public event EventHandler Disposed; + + public bool IsDisposed { + 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() { + Thread.MemoryBarrier(); + if (m_disposed != 0) + throw new ObjectDisposedException(ToString()); + } + /// <summary> + /// Вызывает событие <see cref="Disposed"/> + /// </summary> + /// <param name="disposing">Признак того, что нужно освободить ресурсы, иначе данный метод + /// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого + /// объекта.</param> + /// <remarks> + /// Данный метод вызывается гарантированно один раз даже при одновременном вызове <see cref="Dispose()"/> + /// из нескольких потоков. + /// </remarks> + protected virtual void Dispose(bool disposing) { + if (disposing) { + EventHandler temp = Disposed; + if (temp != null) + temp(this, EventArgs.Empty); + } + } + + public void Dispose() { + if (Interlocked.Increment(ref m_disposed) == 1) { + Dispose(true); + GC.SuppressFinalize(this); + } + } + + /// <summary> + /// Записывает сообщение об утечке объекта. + /// </summary> + protected virtual void ReportObjectLeaks() { + TraceLog.TraceWarning("The object is marked as disposable but isn't disposed properly: {0}", this); + } + + ~Disposable() { + Dispose(false); + ReportObjectLeaks(); + } + } +} \ No newline at end of file