##// END OF EJS Templates
added multithreading support to Disposable class
cin -
r100:673947ce458a v2
parent child
Show More
@@ -1,62 +1,104
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() {
86 if (Interlocked.Increment(ref m_disposed) == 1) {
46 Dispose(true);
87 Dispose(true);
47 GC.SuppressFinalize(this);
88 GC.SuppressFinalize(this);
48 }
89 }
90 }
49
91
50 /// <summary>
92 /// <summary>
51 /// Записывает сообщение об утечке объекта.
93 /// Записывает сообщение об утечке объекта.
52 /// </summary>
94 /// </summary>
53 protected virtual void ReportObjectLeaks() {
95 protected virtual void ReportObjectLeaks() {
54 TraceLog.TraceWarning("The object is marked as disposable but isn't disposed properly: {0}", this);
96 TraceLog.TraceWarning("The object is marked as disposable but isn't disposed properly: {0}", this);
55 }
97 }
56
98
57 ~Disposable() {
99 ~Disposable() {
58 Dispose(false);
100 Dispose(false);
59 ReportObjectLeaks();
101 ReportObjectLeaks();
60 }
102 }
61 }
103 }
62 } No newline at end of file
104 }
General Comments 0
You need to be logged in to leave comments. Login now