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