Disposable.cs
103 lines
| 4.2 KiB
| text/x-csharp
|
CSharpLexer
/ Implab / Disposable.cs
cin
|
r48 | using Implab.Diagnostics; | |
using System; | |||
cin
|
r100 | using System.Threading; | |
using System.IO; | |||
cin
|
r40 | ||
namespace Implab { | |||
cin
|
r48 | /// <summary> | |
/// Объект, поддерживающий освобождение ресурсов. | |||
/// </summary> | |||
cin
|
r40 | public class Disposable : IDisposable { | |
cin
|
r100 | int m_disposed; | |
cin
|
r40 | ||
public event EventHandler Disposed; | |||
public bool IsDisposed { | |||
cin
|
r100 | get { | |
Thread.MemoryBarrier(); | |||
return m_disposed != 0; | |||
} | |||
cin
|
r40 | } | |
cin
|
r100 | /// <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> | |||
cin
|
r40 | protected void AssertNotDisposed() { | |
cin
|
r100 | Thread.MemoryBarrier(); | |
if (m_disposed != 0) | |||
throw new ObjectDisposedException(ToString()); | |||
cin
|
r40 | } | |
cin
|
r48 | /// <summary> | |
cin
|
r100 | /// Вызывает событие <see cref="Disposed"/> | |
cin
|
r48 | /// </summary> | |
/// <param name="disposing">Признак того, что нужно освободить ресурсы, иначе данный метод | |||
/// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого | |||
/// объекта.</param> | |||
/// <remarks> | |||
cin
|
r100 | /// Данный метод вызывается гарантированно один раз даже при одновременном вызове <see cref="Dispose()"/> | |
/// из нескольких потоков. | |||
cin
|
r48 | /// </remarks> | |
cin
|
r40 | protected virtual void Dispose(bool disposing) { | |
cin
|
r100 | if (disposing) { | |
cin
|
r40 | EventHandler temp = Disposed; | |
cin
|
r100 | if (temp != null) | |
temp(this, EventArgs.Empty); | |||
cin
|
r40 | } | |
} | |||
cin
|
r100 | ||
cin
|
r40 | public void Dispose() { | |
cin
|
r100 | if (Interlocked.Increment(ref m_disposed) == 1) { | |
Dispose(true); | |||
GC.SuppressFinalize(this); | |||
} | |||
cin
|
r40 | } | |
cin
|
r48 | /// <summary> | |
/// Записывает сообщение об утечке объекта. | |||
/// </summary> | |||
cin
|
r40 | protected virtual void ReportObjectLeaks() { | |
cin
|
r48 | TraceLog.TraceWarning("The object is marked as disposable but isn't disposed properly: {0}", this); | |
cin
|
r40 | } | |
~Disposable() { | |||
Dispose(false); | |||
ReportObjectLeaks(); | |||
} | |||
} | |||
} |