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
|
|
12 volatile bool m_disposed;
|
|
13
|
|
14 volatile int m_count;
|
|
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
|
|
31 public ObjectPoolWrapper<T> Allocate() {
|
|
32 if (m_disposed)
|
|
33 throw new ObjectDisposedException(this.ToString());
|
|
34
|
|
35 T instance;
|
|
36 if (m_queue.TryDequeue(out instance)) {
|
|
37 Interlocked.Decrement(ref m_count);
|
|
38 return instance;
|
|
39 } else {
|
|
40 instance = m_factory();
|
|
41 }
|
|
42 return new ObjectPoolWrapper<T>(instance, this);
|
|
43 }
|
|
44
|
|
45 public void Release(T instance) {
|
|
46 if (m_count < m_size && !m_disposed) {
|
|
47 Interlocked.Increment(ref m_count);
|
|
48
|
|
49 if (m_cleanup != null)
|
|
50 m_cleanup(instance);
|
|
51
|
|
52 m_queue.Enqueue(instance);
|
|
53
|
|
54 // пока элемент возвращался в кеш, была начата операция освобождения всего кеша
|
|
55 // и возможно уже законцена, в таком случае следует извлечь элемент обратно и
|
|
56 // освободить его. Если операция освобождения кеша еще не заврешилась, то будет
|
|
57 // изъят и освобожден произвольный элемен, что не повлияет на ход всего процесса.
|
|
58 if (m_disposed && m_queue.TryDequeue(out instance))
|
|
59 Safe.Dispose(instance);
|
|
60
|
|
61 } else {
|
|
62 Safe.Dispose(instance);
|
|
63 }
|
|
64 }
|
|
65
|
|
66 protected virtual void Dispose(bool disposing) {
|
|
67 if (disposing) {
|
|
68 m_disposed = true;
|
|
69 T instance;
|
|
70 while (m_queue.TryDequeue(out instance))
|
|
71 Safe.Dispose(instance);
|
|
72 }
|
|
73 }
|
|
74
|
|
75 #region IDisposable implementation
|
|
76
|
|
77 public void Dispose() {
|
|
78 Dispose(true);
|
|
79 GC.SuppressFinalize(this);
|
|
80 }
|
|
81
|
|
82 #endregion
|
|
83 }
|
|
84 }
|
|
85
|