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 // и возможно уже законцена, в таком случае следует извлечь элемент обратно и