Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 15215 was 15189, checked in by pkimmesw, 8 years ago

#2665 Fixed small issues, testet benchmark suite, added INX Expressions

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