comparison Implab/ObjectPool.cs @ 83:397fe8db0806 v2

fixed object pool
author cin
date Mon, 29 Sep 2014 15:49:15 +0400
parents 0363407ee75c
children abe260860bd6
comparison
equal deleted inserted replaced
82:0363407ee75c 83:397fe8db0806
7 readonly Func<T> m_factory; 7 readonly Func<T> m_factory;
8 readonly Action<T> m_cleanup; 8 readonly Action<T> m_cleanup;
9 readonly int m_size; 9 readonly int m_size;
10 readonly MTQueue<T> m_queue = new MTQueue<T>(); 10 readonly MTQueue<T> m_queue = new MTQueue<T>();
11 11
12 volatile bool m_disposed; 12 bool m_disposed;
13 13
14 volatile int m_count; 14 int m_count;
15 15
16 public ObjectPool(Func<T> factory, Action<T> cleanup, int size) { 16 public ObjectPool(Func<T> factory, Action<T> cleanup, int size) {
17 Safe.ArgumentNotNull(factory, "factory"); 17 Safe.ArgumentNotNull(factory, "factory");
18 Safe.ArgumentInRange(size, 1, size, "size"); 18 Safe.ArgumentInRange(size, 1, size, "size");
19 19
26 } 26 }
27 27
28 public ObjectPool(Func<T> factory) : this(factory,null,Environment.ProcessorCount+1) { 28 public ObjectPool(Func<T> factory) : this(factory,null,Environment.ProcessorCount+1) {
29 } 29 }
30 30
31 public ObjectPoolWrapper<T> Allocate() { 31 public ObjectPoolWrapper<T> AllocateAuto() {
32
33 return new ObjectPoolWrapper<T>(Allocate(), this);
34 }
35
36 public T Allocate() {
32 if (m_disposed) 37 if (m_disposed)
33 throw new ObjectDisposedException(this.ToString()); 38 throw new ObjectDisposedException(this.ToString());
34 39
35 T instance; 40 T instance;
36 if (m_queue.TryDequeue(out instance)) { 41 if (m_queue.TryDequeue(out instance)) {
37 Interlocked.Decrement(ref m_count); 42 Interlocked.Decrement(ref m_count);
38 return instance;
39 } else { 43 } else {
40 instance = m_factory(); 44 instance = m_factory();
41 } 45 }
42 return new ObjectPoolWrapper<T>(instance, this); 46 return instance;
43 } 47 }
44 48
45 public void Release(T instance) { 49 public void Release(T instance) {
50 Thread.MemoryBarrier();
46 if (m_count < m_size && !m_disposed) { 51 if (m_count < m_size && !m_disposed) {
47 Interlocked.Increment(ref m_count); 52 Interlocked.Increment(ref m_count);
48 53
49 if (m_cleanup != null) 54 if (m_cleanup != null)
50 m_cleanup(instance); 55 m_cleanup(instance);
53 58
54 // пока элемент возвращался в кеш, была начата операция освобождения всего кеша 59 // пока элемент возвращался в кеш, была начата операция освобождения всего кеша
55 // и возможно уже законцена, в таком случае следует извлечь элемент обратно и 60 // и возможно уже законцена, в таком случае следует извлечь элемент обратно и
56 // освободить его. Если операция освобождения кеша еще не заврешилась, то будет 61 // освободить его. Если операция освобождения кеша еще не заврешилась, то будет
57 // изъят и освобожден произвольный элемен, что не повлияет на ход всего процесса. 62 // изъят и освобожден произвольный элемен, что не повлияет на ход всего процесса.
58 if (m_disposed && m_queue.TryDequeue(out instance)) 63 if (m_disposed && m_queue.TryDequeue(out instance) && instance is IDisposable)
59 Safe.Dispose(instance); 64 ((IDisposable)instance).Dispose() ;
60 65
61 } else { 66 } else {
62 Safe.Dispose(instance); 67 if (instance is IDisposable)
68 ((IDisposable)instance).Dispose();
63 } 69 }
64 } 70 }
65 71
66 protected virtual void Dispose(bool disposing) { 72 protected virtual void Dispose(bool disposing) {
67 if (disposing) { 73 if (disposing) {
68 m_disposed = true; 74 m_disposed = true;
69 T instance; 75 T instance;
70 while (m_queue.TryDequeue(out instance)) 76 while (m_queue.TryDequeue(out instance))
71 Safe.Dispose(instance); 77 if (instance is IDisposable)
78 ((IDisposable)instance).Dispose();
72 } 79 }
73 } 80 }
74 81
75 #region IDisposable implementation 82 #region IDisposable implementation
76 83