Mercurial > pub > ImplabNet
comparison Implab/ObjectPool.cs @ 85:abe260860bd6 v2
fixed JSONXmlReader disposing under ugly mono
ObjectPool is made abstract
author | cin |
---|---|
date | Tue, 30 Sep 2014 16:05:35 +0400 |
parents | 397fe8db0806 |
children | cdaaf4792c22 |
comparison
equal
deleted
inserted
replaced
84:34bb2f32634d | 85:abe260860bd6 |
---|---|
1 using System; | 1 using System; |
2 using Implab.Parallels; | 2 using Implab.Parallels; |
3 using System.Threading; | 3 using System.Threading; |
4 using System.Diagnostics; | |
5 using System.Diagnostics.CodeAnalysis; | |
4 | 6 |
5 namespace Implab { | 7 namespace Implab { |
6 public class ObjectPool<T> : IDisposable { | 8 public abstract class ObjectPool<T> : IDisposable { |
7 readonly Func<T> m_factory; | |
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 | |
12 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] | |
13 static readonly bool _isValueType = typeof(T).IsValueType; | |
11 | 14 |
12 bool m_disposed; | 15 bool m_disposed; |
13 | 16 |
14 int m_count; | 17 int m_count; |
15 | 18 |
16 public ObjectPool(Func<T> factory, Action<T> cleanup, int size) { | 19 protected ObjectPool(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; | 20 m_size = size; |
23 } | 21 } |
24 | 22 |
25 public ObjectPool(Func<T> factory, Action<T> cleanup) : this(factory,cleanup,Environment.ProcessorCount+1) { | 23 protected ObjectPool() : this(Environment.ProcessorCount+1) { |
26 } | |
27 | |
28 public ObjectPool(Func<T> factory) : this(factory,null,Environment.ProcessorCount+1) { | |
29 } | 24 } |
30 | 25 |
31 public ObjectPoolWrapper<T> AllocateAuto() { | 26 public ObjectPoolWrapper<T> AllocateAuto() { |
32 | 27 |
33 return new ObjectPoolWrapper<T>(Allocate(), this); | 28 return new ObjectPoolWrapper<T>(Allocate(), this); |
34 } | 29 } |
35 | 30 |
36 public T Allocate() { | 31 public T Allocate() { |
37 if (m_disposed) | 32 if (m_disposed) |
38 throw new ObjectDisposedException(this.ToString()); | 33 throw new ObjectDisposedException(ToString()); |
39 | 34 |
40 T instance; | 35 T instance; |
41 if (m_queue.TryDequeue(out instance)) { | 36 if (m_queue.TryDequeue(out instance)) { |
42 Interlocked.Decrement(ref m_count); | 37 Interlocked.Decrement(ref m_count); |
43 } else { | 38 } else { |
44 instance = m_factory(); | 39 instance = CreateInstance(); |
40 Debug.Assert(!Object.Equals(instance, default(T)) || _isValueType); | |
45 } | 41 } |
46 return instance; | 42 return instance; |
47 } | 43 } |
48 | 44 |
45 protected abstract T CreateInstance(); | |
46 | |
47 protected virtual void CleanupInstance(T instance) { | |
48 } | |
49 | |
49 public void Release(T instance) { | 50 public void Release(T instance) { |
51 if ( Object.Equals(instance,default(T)) && !_isValueType) | |
52 return; | |
53 | |
50 Thread.MemoryBarrier(); | 54 Thread.MemoryBarrier(); |
51 if (m_count < m_size && !m_disposed) { | 55 if (m_count < m_size && !m_disposed) { |
52 Interlocked.Increment(ref m_count); | 56 Interlocked.Increment(ref m_count); |
53 | 57 |
54 if (m_cleanup != null) | 58 CleanupInstance(instance); |
55 m_cleanup(instance); | |
56 | 59 |
57 m_queue.Enqueue(instance); | 60 m_queue.Enqueue(instance); |
58 | 61 |
59 // пока элемент возвращался в кеш, была начата операция освобождения всего кеша | 62 // пока элемент возвращался в кеш, была начата операция освобождения всего кеша |
60 // и возможно уже законцена, в таком случае следует извлечь элемент обратно и | 63 // и возможно уже законцена, в таком случае следует извлечь элемент обратно и |