Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2665 Fixed Benchmark Problem Definition, Converted LoopExpressions to stateless expressions, Added several unit test to ensure funcionality, Fixed UI bugs

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