152
|
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 }
|