# HG changeset patch
# User cin
# Date 2014-11-05 13:39:56
# Node ID 673947ce458a94e072967b0525301540a7a73a56
# Parent 8ddf1648eca4624d0d2a4e6ea23e0a94793e2d35
added multithreading support to Disposable class
diff --git a/Implab/Disposable.cs b/Implab/Disposable.cs
--- a/Implab/Disposable.cs
+++ b/Implab/Disposable.cs
@@ -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 @@ namespace Implab {
///
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);
+ }
}
///