comparison Implab/DisposablePool.cs @ 117:8beee0d11de6 v2

pool refactoring
author cin
date Tue, 23 Dec 2014 19:48:47 +0300
parents
children 2573b562e328
comparison
equal deleted inserted replaced
116:da56ba7b1aab 117:8beee0d11de6
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;
10 readonly MTQueue<T> m_queue = new MTQueue<T>();
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