##// END OF EJS Templates
pool refactoring
cin -
r117:8beee0d11de6 v2
parent child
Show More
@@ -0,0 +1,90
1 using System;
2 using Implab.Parallels;
3 using System.Threading;
4 using System.Diagnostics;
5 using System.Diagnostics.CodeAnalysis;
6
7 namespace Implab {
8 public abstract class DisposablePool<T> : IDisposable {
9 readonly int m_size;
10 readonly MTQueue<T> m_queue = new MTQueue<T>();
11
12 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
13 static readonly bool _isValueType = typeof(T).IsValueType;
14
15 bool m_disposed;
16
17 int m_count;
18
19 protected DisposablePool(int size) {
20 m_size = size;
21 }
22
23 protected DisposablePool() : this(Environment.ProcessorCount+1) {
24 }
25
26 public T Allocate() {
27 if (m_disposed)
28 throw new ObjectDisposedException(ToString());
29
30 T instance;
31 if (m_queue.TryDequeue(out instance)) {
32 Interlocked.Decrement(ref m_count);
33 } else {
34 instance = CreateInstance();
35 Debug.Assert(!Object.Equals(instance, default(T)) || _isValueType);
36 }
37 return instance;
38 }
39
40 protected abstract T CreateInstance();
41
42 protected virtual void CleanupInstance(T instance) {
43 }
44
45 public void Release(T instance) {
46 if ( Object.Equals(instance,default(T)) && !_isValueType)
47 return;
48
49 Thread.MemoryBarrier();
50 if (m_count < m_size && !m_disposed) {
51 Interlocked.Increment(ref m_count);
52
53 CleanupInstance(instance);
54
55 m_queue.Enqueue(instance);
56
57 // пока элемент возвращался в кеш, была начата операция освобождения всего кеша
58 // и возможно уже законцена, в таком случае следует извлечь элемент обратно и
59 // освободить его. Если операция освобождения кеша еще не заврешилась, то будет
60 // изъят и освобожден произвольный элемен, что не повлияет на ход всего процесса.
61 if (m_disposed && m_queue.TryDequeue(out instance) && instance is IDisposable)
62 ((IDisposable)instance).Dispose() ;
63
64 } else {
65 if (instance is IDisposable)
66 ((IDisposable)instance).Dispose();
67 }
68 }
69
70 protected virtual void Dispose(bool disposing) {
71 if (disposing) {
72 m_disposed = true;
73 T instance;
74 while (m_queue.TryDequeue(out instance))
75 if (instance is IDisposable)
76 ((IDisposable)instance).Dispose();
77 }
78 }
79
80 #region IDisposable implementation
81
82 public void Dispose() {
83 Dispose(true);
84 GC.SuppressFinalize(this);
85 }
86
87 #endregion
88 }
89 }
90
@@ -127,7 +127,6
127 <Compile Include="Parsing\StarToken.cs" />
127 <Compile Include="Parsing\StarToken.cs" />
128 <Compile Include="Parsing\SymbolToken.cs" />
128 <Compile Include="Parsing\SymbolToken.cs" />
129 <Compile Include="Parsing\Token.cs" />
129 <Compile Include="Parsing\Token.cs" />
130 <Compile Include="SafePool.cs" />
131 <Compile Include="ServiceLocator.cs" />
130 <Compile Include="ServiceLocator.cs" />
132 <Compile Include="TaskController.cs" />
131 <Compile Include="TaskController.cs" />
133 <Compile Include="ProgressInitEventArgs.cs" />
132 <Compile Include="ProgressInitEventArgs.cs" />
@@ -139,7 +138,6
139 <Compile Include="PromiseExtensions.cs" />
138 <Compile Include="PromiseExtensions.cs" />
140 <Compile Include="TransientPromiseException.cs" />
139 <Compile Include="TransientPromiseException.cs" />
141 <Compile Include="SyncContextPromise.cs" />
140 <Compile Include="SyncContextPromise.cs" />
142 <Compile Include="ObjectPool.cs" />
143 <Compile Include="Diagnostics\OperationContext.cs" />
141 <Compile Include="Diagnostics\OperationContext.cs" />
144 <Compile Include="Diagnostics\TraceContext.cs" />
142 <Compile Include="Diagnostics\TraceContext.cs" />
145 <Compile Include="Diagnostics\LogEventArgs.cs" />
143 <Compile Include="Diagnostics\LogEventArgs.cs" />
@@ -150,6 +148,8
150 <Compile Include="Parallels\MTCustomQueue.cs" />
148 <Compile Include="Parallels\MTCustomQueue.cs" />
151 <Compile Include="Parallels\MTCustomQueueNode.cs" />
149 <Compile Include="Parallels\MTCustomQueueNode.cs" />
152 <Compile Include="ComponentContainer.cs" />
150 <Compile Include="ComponentContainer.cs" />
151 <Compile Include="DisposablePool.cs" />
152 <Compile Include="ObjectPool.cs" />
153 </ItemGroup>
153 </ItemGroup>
154 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
154 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
155 <ItemGroup />
155 <ItemGroup />
@@ -1,90 +1,60
1 using System;
1 using Implab.Parallels;
2 using Implab.Parallels;
2 using System;
3 using System.Threading;
3 using System.Threading;
4 using System.Diagnostics;
4
5 using System.Diagnostics.CodeAnalysis;
5 namespace Implab {
6
6 /// <summary>
7 namespace Implab {
7 /// Базовый класс для создания пулов объектов.
8 public abstract class ObjectPool<T> : IDisposable {
8 /// </summary>
9 readonly int m_size;
9 /// <remarks>
10 readonly MTQueue<T> m_queue = new MTQueue<T>();
10 /// <para>Пул объектов позволяет многократно использовать один и тотже объект,
11
11 /// что актуально для объектов, создание которых требует существенных ресурсов.
12 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
12 /// Пул объектов использует слабые ссылки, чтобы не препятствовать освобождению
13 static readonly bool _isValueType = typeof(T).IsValueType;
13 /// ресурсов и создает новые объекты при необходимости.</para>
14
14 /// <para>
15 bool m_disposed;
15 /// Наследники должны реализовывать метод <see cref="CreateInstance()"/> для создания
16
16 /// новых экземпляров.
17 int m_count;
17 /// </para>
18
18 /// <para>Пул поддерживает обращения сразу из нескольких потоков.</para>
19 protected ObjectPool(int size) {
19 /// </remarks>
20 m_size = size;
20 public abstract class ObjectPool<T> where T : class {
21 }
21 readonly MTQueue<WeakReference> m_queue = new MTQueue<WeakReference>();
22
22 readonly int m_size;
23 protected ObjectPool() : this(Environment.ProcessorCount+1) {
23 int m_count = 0;
24 }
24
25
25 protected ObjectPool() : this(Environment.ProcessorCount+1) {
26 public T Allocate() {
26
27 if (m_disposed)
27 }
28 throw new ObjectDisposedException(ToString());
28
29
29 protected ObjectPool(int size) {
30 T instance;
30 Safe.ArgumentInRange(size,1,size,"size");
31 if (m_queue.TryDequeue(out instance)) {
31
32 Interlocked.Decrement(ref m_count);
32 m_size = size;
33 } else {
33 }
34 instance = CreateInstance();
34
35 Debug.Assert(!Object.Equals(instance, default(T)) || _isValueType);
35 protected abstract T CreateInstance();
36 }
36
37 return instance;
37 protected virtual void CleanupInstance(T instance) {
38 }
38 }
39
39
40 protected abstract T CreateInstance();
40 public T Allocate() {
41
41 WeakReference reference;
42 protected virtual void CleanupInstance(T instance) {
42 while (m_queue.TryDequeue(out reference)) {
43 }
43 Interlocked.Decrement(ref m_count);
44
44 object instance = reference.Target;
45 public void Release(T instance) {
45 if (instance == null)
46 if ( Object.Equals(instance,default(T)) && !_isValueType)
46 continue;
47 return;
47 return (T)instance;
48
48 }
49 Thread.MemoryBarrier();
49 return CreateInstance();
50 if (m_count < m_size && !m_disposed) {
50 }
51 Interlocked.Increment(ref m_count);
51
52
52 public void Release(T instance) {
53 CleanupInstance(instance);
53 if (m_count < m_size && instance != null) {
54
54 Interlocked.Increment(ref m_count);
55 m_queue.Enqueue(instance);
55 CleanupInstance(instance);
56
56 m_queue.Enqueue(new WeakReference(instance));
57 // пока элемент возвращался в кеш, была начата операция освобождения всего кеша
57 }
58 // и возможно уже законцена, в таком случае следует извлечь элемент обратно и
58 }
59 // освободить его. Если операция освобождения кеша еще не заврешилась, то будет
59 }
60 // изъят и освобожден произвольный элемен, что не повлияет на ход всего процесса.
60 }
61 if (m_disposed && m_queue.TryDequeue(out instance) && instance is IDisposable)
62 ((IDisposable)instance).Dispose() ;
63
64 } else {
65 if (instance is IDisposable)
66 ((IDisposable)instance).Dispose();
67 }
68 }
69
70 protected virtual void Dispose(bool disposing) {
71 if (disposing) {
72 m_disposed = true;
73 T instance;
74 while (m_queue.TryDequeue(out instance))
75 if (instance is IDisposable)
76 ((IDisposable)instance).Dispose();
77 }
78 }
79
80 #region IDisposable implementation
81
82 public void Dispose() {
83 Dispose(true);
84 GC.SuppressFinalize(this);
85 }
86
87 #endregion
88 }
89 }
90
@@ -5,7 +5,7 namespace Implab {
5 /// <summary>
5 /// <summary>
6 /// Коллекция сервисов, позволяет регистрировать и получать сервисы.
6 /// Коллекция сервисов, позволяет регистрировать и получать сервисы.
7 /// </summary>
7 /// </summary>
8 public class ServiceLocator: Component, IServiceLocator, IServiceProvider {
8 public class ServiceLocator: Disposable, IServiceLocator, IServiceProvider {
9 // запись о сервисе
9 // запись о сервисе
10 struct ServiceEntry : IDisposable {
10 struct ServiceEntry : IDisposable {
11 public object service; // сервис
11 public object service; // сервис
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now