Mercurial > pub > ImplabNet
comparison Implab/Components/ObjectPool.cs @ 152:240aa6994018 v2
component model refactoring
author | cin |
---|---|
date | Thu, 11 Feb 2016 01:56:27 +0300 |
parents | |
children | 2dcdee4c0810 |
comparison
equal
deleted
inserted
replaced
151:ec91a6dfa5b3 | 152:240aa6994018 |
---|---|
1 using Implab.Parallels; | |
2 using System; | |
3 using System.Threading; | |
4 | |
5 namespace Implab.Components { | |
6 /// <summary> | |
7 /// Базовый класс для создания пулов объектов. | |
8 /// </summary> | |
9 /// <remarks> | |
10 /// <para>Пул объектов позволяет многократно использовать один и тотже объект, | |
11 /// что актуально для объектов, создание которых требует существенных ресурсов. | |
12 /// Пул объектов использует слабые ссылки, чтобы не препятствовать освобождению | |
13 /// ресурсов и создает новые объекты при необходимости.</para> | |
14 /// <para> | |
15 /// Наследники должны реализовывать метод <see cref="CreateInstance()"/> для создания | |
16 /// новых экземпляров. | |
17 /// </para> | |
18 /// <para>Пул поддерживает обращения сразу из нескольких потоков.</para> | |
19 /// </remarks> | |
20 public abstract class ObjectPool<T> where T : class { | |
21 readonly AsyncQueue<WeakReference> m_queue = new AsyncQueue<WeakReference>(); | |
22 readonly int m_size; | |
23 int m_count = 0; | |
24 | |
25 protected ObjectPool() : this(Environment.ProcessorCount+1) { | |
26 | |
27 } | |
28 | |
29 protected ObjectPool(int size) { | |
30 Safe.ArgumentInRange(size,1,size,"size"); | |
31 | |
32 m_size = size; | |
33 } | |
34 | |
35 protected abstract T CreateInstance(); | |
36 | |
37 protected virtual void CleanupInstance(T instance) { | |
38 } | |
39 | |
40 public T Allocate() { | |
41 WeakReference reference; | |
42 while (m_queue.TryDequeue(out reference)) { | |
43 Interlocked.Decrement(ref m_count); | |
44 object instance = reference.Target; | |
45 if (instance == null) | |
46 continue; | |
47 return (T)instance; | |
48 } | |
49 return CreateInstance(); | |
50 } | |
51 | |
52 public void Release(T instance) { | |
53 if (m_count < m_size && instance != null) { | |
54 Interlocked.Increment(ref m_count); | |
55 CleanupInstance(instance); | |
56 m_queue.Enqueue(new WeakReference(instance)); | |
57 } | |
58 } | |
59 } | |
60 } |