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