Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Data/Pool/ManagedPoolProvider.cs @ 14875

Last change on this file since 14875 was 14875, checked in by pkimmesw, 7 years ago

#2665 BenchmarkSuite, all examples, partially tested, VectorExpressions added

File size: 3.7 KB
Line 
1using System.Collections.Generic;
2
3namespace HeuristicLab.Problems.ProgramSynthesis.Push.Data.Pool {
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  public interface IManagedPool<T> : IDisposable where T : class, IPooledObject {
11    T Get(bool reset = true);
12  }
13
14  public class ManagedPoolProvider<T> where T : class, IPooledObject {
15    private readonly ConcurrentStack<T[]> partitions = new ConcurrentStack<T[]>();
16    private readonly ObjectPool<IManagedPool<T>> managedPools;
17    private readonly BinaryFormatter binaryFormatter = new BinaryFormatter();
18    private byte[] dummyPartition;
19
20    private static readonly FieldInfo InternalListArrayProperty = typeof(List<T[]>).GetField(
21      "_items",
22      BindingFlags.NonPublic | BindingFlags.Instance);
23
24    private readonly Func<T> factory;
25
26    public readonly int PartitionSize;
27    public readonly int MaxParitionCount;
28    public const int DefaultMaxInstanceCount = 65536;
29
30    public ManagedPoolProvider(int partitionSize, Func<T> factory, int? maxPartitionCount = null) {
31      PartitionSize = partitionSize;
32      MaxParitionCount = maxPartitionCount ?? DefaultMaxInstanceCount / PartitionSize;
33      this.factory = factory;
34
35      managedPools = new ObjectPool<IManagedPool<T>>(() => new ManagedPool(this));
36    }
37    public int InstanceCount { get { return partitions.Count * PartitionSize; } }
38
39    private void InitDummyPartition(Func<T> factory) {
40      var temp = new T[PartitionSize];
41
42      for (var i = 0u; i < PartitionSize; i++) {
43        temp[i] = factory();
44      }
45
46      using (var memoryStream = new MemoryStream()) {
47        binaryFormatter.Serialize(memoryStream, temp);
48        dummyPartition = memoryStream.ToArray();
49      }
50    }
51
52    public void ReleasePartitions(List<T[]> releasedPartitions) {
53      if (partitions.Count < MaxParitionCount)
54        partitions.PushRange((T[][])InternalListArrayProperty.GetValue(releasedPartitions), 0, releasedPartitions.Count);
55    }
56
57    private T[] GetPartition() {
58      T[] partition;
59      return partitions.TryPop(out partition) ? partition : CloneDummyPartition();
60    }
61
62    private T[] CloneDummyPartition() {
63      if (dummyPartition == null)
64        InitDummyPartition(factory);
65
66      using (var memoryStream = new MemoryStream(dummyPartition)) {
67        memoryStream.Seek(0, SeekOrigin.Begin);
68
69        return (T[])binaryFormatter.Deserialize(memoryStream);
70      }
71    }
72
73    public IManagedPool<T> CreatePool() {
74      return managedPools.Allocate();
75    }
76
77    private class ManagedPool : IManagedPool<T> {
78      private readonly ManagedPoolProvider<T> provider;
79      private readonly List<T[]> partitions = new List<T[]>();
80      private T[] currentPartition;
81      private int entryIndex;
82
83      public ManagedPool(ManagedPoolProvider<T> provider) {
84        this.provider = provider;
85        entryIndex = provider.PartitionSize;
86      }
87
88      public T Get(bool resetEntry = true) {
89        if (entryIndex == provider.PartitionSize) {
90          currentPartition = provider.GetPartition();
91          partitions.Add(currentPartition);
92          entryIndex = 0;
93        }
94
95        var entry = currentPartition[entryIndex++];
96        if (resetEntry) entry.Reset();
97        return entry;
98      }
99
100      public void Dispose() {
101        if (partitions.Count > 0) {
102          provider.ReleasePartitions(partitions);
103          partitions.Clear();
104          currentPartition = null;
105          entryIndex = provider.PartitionSize;
106        }
107
108        provider.managedPools.Free(this);
109      }
110    }
111  }
112}
Note: See TracBrowser for help on using the repository browser.