Mercurial > pub > ImplabNet
comparison Implab/ObjectPool.cs @ 82:0363407ee75c v2
added object pool
author | cin |
---|---|
date | Mon, 29 Sep 2014 05:04:32 +0400 |
parents | |
children | 397fe8db0806 |
comparison
equal
deleted
inserted
replaced
81:2c5631b43c7d | 82:0363407ee75c |
---|---|
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 |