Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2895_PushGP_GenealogyAnalysis/HeuristicLab.Problems.ProgramSynthesis/Push/Data/Pool/ManagedPoolProvider.cs @ 16724

Last change on this file since 16724 was 15771, checked in by bburlacu, 7 years ago

#2895: Add solution skeleton for PushGP with genealogy analysis.

File size: 4.2 KB
Line 
1using System.Collections.Generic;
2
3namespace HeuristicLab.Problems.ProgramSynthesis {
4  using System;
5  using System.Collections.Concurrent;
6  using System.IO;
7  using System.Reflection;
8  using System.Runtime.Serialization.Formatters.Binary;
9
10  using Microsoft.IO;
11
12  public interface IManagedPool<T> : IDisposable where T : class, IPooledObject {
13    T Get(bool reset = true);
14    void Release();
15  }
16
17  public class ManagedPoolProvider<T> where T : class, IPooledObject {
18    private readonly ConcurrentStack<T[]> partitions = new ConcurrentStack<T[]>();
19    private readonly ObjectPool<IManagedPool<T>> managedPools;
20    private readonly BinaryFormatter binaryFormatter = new BinaryFormatter();
21    private readonly RecyclableMemoryStreamManager recyclableMemoryStreamManager = new RecyclableMemoryStreamManager();
22    private byte[] dummyPartition;
23    private volatile object dummyCreationLockObject = new object();
24
25    private static readonly FieldInfo InternalListArrayProperty = typeof(List<T[]>).GetField(
26      "_items",
27      BindingFlags.NonPublic | BindingFlags.Instance);
28
29    private readonly Func<T> factory;
30
31    public readonly int PartitionSize;
32    public readonly int MaxPartitionCount;
33    public const int DefaultMaxInstanceCount = 65536;
34
35    public ManagedPoolProvider(int partitionSize, Func<T> factory, int? maxPartitionCount = null) {
36      PartitionSize = partitionSize;
37      MaxPartitionCount = maxPartitionCount ?? DefaultMaxInstanceCount / PartitionSize;
38      this.factory = factory;
39
40      managedPools = new ObjectPool<IManagedPool<T>>(() => new ManagedPool(this));
41    }
42    public int InstanceCount { get { return partitions.Count * PartitionSize; } }
43
44    public void Clear() {
45      dummyPartition = null;
46      managedPools.Clear();
47      partitions.Clear();
48    }
49
50    public void ReleasePartitions(List<T[]> releasedPartitions) {
51      if (partitions.Count < MaxPartitionCount)
52        partitions.PushRange((T[][])InternalListArrayProperty.GetValue(releasedPartitions), 0, releasedPartitions.Count);
53    }
54
55    private T[] GetPartition() {
56      T[] partition;
57      return partitions.TryPop(out partition) ? partition : CloneDummyPartition();
58    }
59
60    private T[] CloneDummyPartition() {
61      // init dummy partition
62      if (dummyPartition == null) {
63        lock (dummyCreationLockObject) {
64          if (dummyPartition == null) {
65            var temp = new T[PartitionSize];
66
67            for (var i = 0u; i < PartitionSize; i++) {
68              temp[i] = factory();
69            }
70
71            using (var ms = recyclableMemoryStreamManager.GetStream("dummyPartition")) {
72              binaryFormatter.Serialize(ms, temp);
73              dummyPartition = ms.ToArray();
74            }
75          }
76        }
77      }
78
79      using (var ms = recyclableMemoryStreamManager.GetStream("dummyPartition", dummyPartition, 0, dummyPartition.Length)) {
80        ms.Seek(0, SeekOrigin.Begin);
81        var result = (T[])binaryFormatter.Deserialize(ms);
82        return result;
83      }
84    }
85
86    public IManagedPool<T> CreatePool() {
87      return managedPools.Allocate();
88    }
89
90    private class ManagedPool : IManagedPool<T> {
91      private readonly ManagedPoolProvider<T> provider;
92      private readonly List<T[]> partitions = new List<T[]>();
93      private T[] currentPartition;
94      private int entryIndex;
95
96      public ManagedPool(ManagedPoolProvider<T> provider) {
97        this.provider = provider;
98        entryIndex = provider.PartitionSize;
99      }
100
101      public T Get(bool resetEntry = true) {
102        if (entryIndex == provider.PartitionSize) {
103          currentPartition = provider.GetPartition();
104          partitions.Add(currentPartition);
105          entryIndex = 0;
106        }
107
108        var entry = currentPartition[entryIndex++];
109        if (resetEntry) entry.Reset();
110        return entry;
111      }
112
113      public void Release() {
114        if (partitions.Count > 0) {
115          provider.ReleasePartitions(partitions);
116          partitions.Clear();
117          currentPartition = null;
118          entryIndex = provider.PartitionSize;
119        }
120      }
121
122      public void Dispose() {
123        Release();
124
125        provider.managedPools.Free(this);
126      }
127    }
128  }
129}
Note: See TracBrowser for help on using the repository browser.