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