| @@ -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 |  |  | 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 |  |  | 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: |  | 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
                    
                