Mercurial > pub > ImplabNet
view Implab/Disposable.cs @ 129:471f596b2603 v2
Added SharedLock to synchronization routines
author | cin |
---|---|
date | Thu, 29 Jan 2015 18:31:06 +0300 |
parents | 673947ce458a |
children |
line wrap: on
line source
using Implab.Diagnostics; using System; using System.Threading; using System.IO; namespace Implab { /// <summary> /// Объект, поддерживающий освобождение ресурсов. /// </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(); } } }