Mercurial > pub > ImplabNet
annotate Implab/DisposablePool.cs @ 147:25cdef49102f v2
sync
author | cin |
---|---|
date | Tue, 17 Mar 2015 08:25:35 +0300 |
parents | 2573b562e328 |
children |
rev | line source |
---|---|
117 | 1 using System; |
2 using Implab.Parallels; | |
3 using System.Threading; | |
4 using System.Diagnostics; | |
5 using System.Diagnostics.CodeAnalysis; | |
6 | |
7 namespace Implab { | |
8 public abstract class DisposablePool<T> : IDisposable { | |
9 readonly int m_size; | |
119
2573b562e328
Promises rewritten, added improved version of AsyncQueue
cin
parents:
117
diff
changeset
|
10 readonly AsyncQueue<T> m_queue = new AsyncQueue<T>(); |
117 | 11 |
12 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] | |
13 static readonly bool _isValueType = typeof(T).IsValueType; | |
14 | |
15 bool m_disposed; | |
16 | |
17 int m_count; | |
18 | |
19 protected DisposablePool(int size) { | |
20 m_size = size; | |
21 } | |
22 | |
23 protected DisposablePool() : this(Environment.ProcessorCount+1) { | |
24 } | |
25 | |
26 public T Allocate() { | |
27 if (m_disposed) | |
28 throw new ObjectDisposedException(ToString()); | |
29 | |
30 T instance; | |
31 if (m_queue.TryDequeue(out instance)) { | |
32 Interlocked.Decrement(ref m_count); | |
33 } else { | |
34 instance = CreateInstance(); | |
35 Debug.Assert(!Object.Equals(instance, default(T)) || _isValueType); | |
36 } | |
37 return instance; | |
38 } | |
39 | |
40 protected abstract T CreateInstance(); | |
41 | |
42 protected virtual void CleanupInstance(T instance) { | |
43 } | |
44 | |
45 public void Release(T instance) { | |
46 if ( Object.Equals(instance,default(T)) && !_isValueType) | |
47 return; | |
48 | |
49 Thread.MemoryBarrier(); | |
50 if (m_count < m_size && !m_disposed) { | |
51 Interlocked.Increment(ref m_count); | |
52 | |
53 CleanupInstance(instance); | |
54 | |
55 m_queue.Enqueue(instance); | |
56 | |
57 // пока элемент возвращался в кеш, была начата операция освобождения всего кеша | |
58 // и возможно уже законцена, в таком случае следует извлечь элемент обратно и | |
59 // освободить его. Если операция освобождения кеша еще не заврешилась, то будет | |
60 // изъят и освобожден произвольный элемен, что не повлияет на ход всего процесса. | |
61 if (m_disposed && m_queue.TryDequeue(out instance) && instance is IDisposable) | |
62 ((IDisposable)instance).Dispose() ; | |
63 | |
64 } else { | |
65 if (instance is IDisposable) | |
66 ((IDisposable)instance).Dispose(); | |
67 } | |
68 } | |
69 | |
70 protected virtual void Dispose(bool disposing) { | |
71 if (disposing) { | |
72 m_disposed = true; | |
73 T instance; | |
74 while (m_queue.TryDequeue(out instance)) | |
75 if (instance is IDisposable) | |
76 ((IDisposable)instance).Dispose(); | |
77 } | |
78 } | |
79 | |
80 #region IDisposable implementation | |
81 | |
82 public void Dispose() { | |
83 Dispose(true); | |
84 GC.SuppressFinalize(this); | |
85 } | |
86 | |
87 #endregion | |
88 } | |
89 } | |
90 |