view Implab/Components/Disposable.cs @ 209:a867536c68fc v2

Bound promise to CancellationToken Added new states to ExecutionSate enum. Added Safe.Guard() method to handle cleanup of the result of the promise
author cin
date Wed, 16 Nov 2016 03:06:08 +0300
parents 7d07503621fe
children 9ee78a345738
line wrap: on
line source

using Implab.Diagnostics;
using System;
using System.Diagnostics.CodeAnalysis;
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);
            }
        }

        [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")]
        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();
        }
    }
}