Mercurial > pub > ImplabNet
comparison Implab/Disposable.cs @ 100:673947ce458a v2
added multithreading support to Disposable class
author | cin |
---|---|
date | Wed, 05 Nov 2014 16:39:56 +0300 |
parents | d9d794b61bb9 |
children |
comparison
equal
deleted
inserted
replaced
99:8ddf1648eca4 | 100:673947ce458a |
---|---|
1 using Implab.Diagnostics; | 1 using Implab.Diagnostics; |
2 using System; | 2 using System; |
3 using System.Collections.Generic; | 3 using System.Threading; |
4 using System.Diagnostics; | 4 using System.IO; |
5 using System.Linq; | |
6 using System.Web; | |
7 | 5 |
8 namespace Implab { | 6 namespace Implab { |
9 /// <summary> | 7 /// <summary> |
10 /// Объект, поддерживающий освобождение ресурсов. | 8 /// Объект, поддерживающий освобождение ресурсов. |
11 /// </summary> | 9 /// </summary> |
12 public class Disposable : IDisposable { | 10 public class Disposable : IDisposable { |
13 | 11 |
14 bool m_disposed; | 12 int m_disposed; |
15 | 13 |
16 public event EventHandler Disposed; | 14 public event EventHandler Disposed; |
17 | 15 |
18 public bool IsDisposed { | 16 public bool IsDisposed { |
19 get { return m_disposed; } | 17 get { |
18 Thread.MemoryBarrier(); | |
19 return m_disposed != 0; | |
20 } | |
20 } | 21 } |
21 | 22 |
23 /// <summary> | |
24 /// Asserts the object is not disposed. | |
25 /// </summary> | |
26 /// <exception cref="ObjectDisposedException">The object is disposed</exception> | |
27 /// <remarks> | |
28 /// Успешная проверка того, что объект не освобожден еще не гарантирует, что он не | |
29 /// будет освобожден сразу после нее, поэтому методы использующие проверку должны | |
30 /// учитывать, что объект может быть освобожден из параллельного потока. | |
31 /// Данны метод служит для упрощения отладки ошибок при использовании объекта после его | |
32 /// освобождения. | |
33 /// </remarks> | |
34 /// <example> | |
35 /// // пример синхронизированного освобождения ресурсов | |
36 /// class FileStore : Disposable { | |
37 /// readonly TextWriter m_file; | |
38 /// readonly obejct m_sync = new object(); | |
39 /// | |
40 /// public FileStore(string file) { | |
41 /// m_file = new TextWriter(File.OpenWrite(file)); | |
42 /// } | |
43 /// | |
44 /// public void Write(string text) { | |
45 /// lock(m_sync) { | |
46 /// AssertNotDisposed(); | |
47 /// m_file.Write(text); | |
48 /// } | |
49 /// } | |
50 /// | |
51 /// protected override void Dispose(bool disposing) { | |
52 /// if (disposing) | |
53 /// lock(m_sync) { | |
54 /// m_file.Dipose(); | |
55 /// base.Dispose(true); | |
56 /// } | |
57 /// else | |
58 /// base.Dispose(false); | |
59 /// } | |
60 /// } | |
61 /// <example> | |
22 protected void AssertNotDisposed() { | 62 protected void AssertNotDisposed() { |
23 if (m_disposed) | 63 Thread.MemoryBarrier(); |
24 throw new ObjectDisposedException(this.ToString()); | 64 if (m_disposed != 0) |
65 throw new ObjectDisposedException(ToString()); | |
25 } | 66 } |
26 /// <summary> | 67 /// <summary> |
27 /// Переводит объект в состояние <c>Disposed</c> и вызывает событие <see cref="Disposed"/> | 68 /// Вызывает событие <see cref="Disposed"/> |
28 /// </summary> | 69 /// </summary> |
29 /// <param name="disposing">Признак того, что нужно освободить ресурсы, иначе данный метод | 70 /// <param name="disposing">Признак того, что нужно освободить ресурсы, иначе данный метод |
30 /// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого | 71 /// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого |
31 /// объекта.</param> | 72 /// объекта.</param> |
32 /// <remarks> | 73 /// <remarks> |
33 /// Данный метод осуществляет проверку того, что объект уже был освобожден, чтобы не вызывать | 74 /// Данный метод вызывается гарантированно один раз даже при одновременном вызове <see cref="Dispose()"/> |
34 /// событие <see cref="Disposed"/>. Не поддерживает многопоточность. | 75 /// из нескольких потоков. |
35 /// </remarks> | 76 /// </remarks> |
36 protected virtual void Dispose(bool disposing) { | 77 protected virtual void Dispose(bool disposing) { |
37 if (disposing && !m_disposed) { | 78 if (disposing) { |
38 m_disposed = true; | |
39 | |
40 EventHandler temp = Disposed; | 79 EventHandler temp = Disposed; |
41 if (temp != null) | 80 if (temp != null) |
42 temp(this,EventArgs.Empty); | 81 temp(this, EventArgs.Empty); |
43 } | 82 } |
44 } | 83 } |
84 | |
45 public void Dispose() { | 85 public void Dispose() { |
46 Dispose(true); | 86 if (Interlocked.Increment(ref m_disposed) == 1) { |
47 GC.SuppressFinalize(this); | 87 Dispose(true); |
88 GC.SuppressFinalize(this); | |
89 } | |
48 } | 90 } |
49 | 91 |
50 /// <summary> | 92 /// <summary> |
51 /// Записывает сообщение об утечке объекта. | 93 /// Записывает сообщение об утечке объекта. |
52 /// </summary> | 94 /// </summary> |