Disposable.cs
102 lines
| 4.2 KiB
| text/x-csharp
|
CSharpLexer
|
|
r152 | 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(); | |||
| } | |||
| } | |||
| } |
