diff --git a/ManagedPool.sln b/ManagedPool.sln
new file mode 100644
index 0000000..d792b9d
--- /dev/null
+++ b/ManagedPool.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.271
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ManagedPool", "ManagedPool\ManagedPool.csproj", "{6E45952C-6966-4CF0-9C32-7A35D54326FE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6E45952C-6966-4CF0-9C32-7A35D54326FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6E45952C-6966-4CF0-9C32-7A35D54326FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6E45952C-6966-4CF0-9C32-7A35D54326FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6E45952C-6966-4CF0-9C32-7A35D54326FE}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {0737324E-EA5C-4D9A-8EF2-90C8717E38E3}
+ EndGlobalSection
+EndGlobal
diff --git a/ManagedPool/ManagedPool.csproj b/ManagedPool/ManagedPool.csproj
new file mode 100644
index 0000000..bc41c57
--- /dev/null
+++ b/ManagedPool/ManagedPool.csproj
@@ -0,0 +1,13 @@
+
+
+
+ netcoreapp2.1
+ false
+ eu.railduction.netcore.dll.ManagedPool
+ 1.1.0
+ false
+ true
+ eu.railduction_assembly-key.pfx
+
+
+
diff --git a/ManagedPool/Pool_T_.cs b/ManagedPool/Pool_T_.cs
new file mode 100644
index 0000000..c331d80
--- /dev/null
+++ b/ManagedPool/Pool_T_.cs
@@ -0,0 +1,269 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace eu.railduction.netcore.dll.ManagedPool
+{
+ public class Pool where T : class
+ {
+ private Func creator;
+ /// Method to handle item-spawning (needs to return the item-type)
+ public Func Creator { get => creator; set => creator = value; }
+
+ private Func healthChecker = (T) => { return true; };
+ /// Method to handle item-health-checking (useful for unstable items)
+ /// While running the health-check, the Thread will be blocked!
+ public Func HealthChecker { get => healthChecker; set => healthChecker = value; }
+
+ private Action destructor;
+ /// Method to handle item-deleting/killing (needs to take the item-type as parameter)
+ public Action Destructor { get => destructor; set => destructor = value; }
+
+ private ConcurrentStack pool = new ConcurrentStack();
+ private int current = 0, max = 100, min = 10, batch = 5, increaseBuffer = 5, decreaseBuffer = 10;
+
+ /// The current amount of items in the pool
+ public int Current { get => min; }
+ /// The current amount of items avaiaible in the pool
+ public int CurrentAvaiaible { get => pool.Count; }
+
+ /// The minimum amount of items in the pool
+ public int Min { get => min; set => min = value; }
+ /// The maximum amount of items in the pool
+ public int Max { get => max; set => max = value; }
+ /// Amount if items being spawned at a time if needed
+ public int Batch { get => batch; set => batch = value; }
+ /// If less items are in the pool that the buffer, it will spawn 'batch'-amount
+ public int IncreaseBuffer { get => increaseBuffer; set => increaseBuffer = value; }
+ /// If more items are in the pool that the buffer, it will delete/kill the overflowing items
+ public int DecreaseBuffer { get => decreaseBuffer; set => decreaseBuffer = value; }
+
+ ///
+ /// Creates a managed pool
+ /// Will automatically spawn items
+ ///
+ /// The minimum amount of items in the pool
+ /// The maximum amount of items in the pool
+ /// Amount if items being spawned at a time if needed
+ /// If less items are in the pool than the , it will spawn -amount
+ /// If more items are in the pool than the , it will delete/kill the overflowing items
+ /// Method to handle item-spawning (needs to return the item-type)
+ /// Method to handle item-deleting/killing (needs to take the item-type as parameter)
+ public Pool(int min, int max, int batch, int increaseBuffer, int decreaseBuffer, Func creator, Action destructor)
+ {
+ this.min = min;
+ this.max = max;
+ this.batch = batch;
+ this.increaseBuffer = increaseBuffer;
+ this.decreaseBuffer = decreaseBuffer;
+
+ // Validate objects state
+ validate();
+
+ this.creator = creator;
+ this.destructor = destructor;
+
+ // Create the minimum amount of objects
+ Task.Run(() => createNewObjects(min));
+ }
+
+ ///
+ /// Creates a managed pool
+ /// Will automatically spawn items
+ /// The health-check is run before an item is used for execution
+ ///
+ /// The minimum amount of items in the pool
+ /// The maximum amount of items in the pool
+ /// Amount if items being spawned at a time if needed
+ /// If less items are in the pool than the , it will spawn -amount
+ /// If more items are in the pool than the , it will delete/kill the overflowing items
+ /// Method to handle item-spawning
+ /// Method to handle item-deleting/killing
+ /// Method to handle item-health-checking (useful for unstable items)
+ /// While running the health-check, the Thread will be blocked!
+ public Pool(int min, int max, int batch, int increaseBuffer, int decreaseBuffer, Func creator, Action destructor, Func healthChecker)
+ {
+ this.min = min;
+ this.max = max;
+ this.batch = batch;
+ this.increaseBuffer = increaseBuffer;
+ this.decreaseBuffer = decreaseBuffer;
+
+ // Validate objects state
+ validate();
+
+ this.creator = creator;
+ this.destructor = destructor;
+ this.healthChecker = healthChecker;
+
+ // Create the minimum amount of objects
+ Task.Run(() => createNewObjects(min));
+ }
+
+ private void validate()
+ {
+ if (min <= 0) throw new InvalidOperationException($"Invalid parameter min='{min}'. Must be at least '1'!");
+ if (max < min) throw new InvalidOperationException($"Invalid parameter max='{max}'. Must be at least min='{min}'!");
+ if (batch <= 0) throw new InvalidOperationException($"Invalid parameter batch='{batch}'. Must be at least '1'!");
+ if (increaseBuffer <= 0) throw new InvalidOperationException($"Invalid parameter increaseBuffer='{increaseBuffer}'. Must be at least '1'!");
+ if (decreaseBuffer <= 0) throw new InvalidOperationException($"Invalid parameter decreaseBuffer='{decreaseBuffer}'. Must be at least '1'!");
+ }
+
+ ///
+ /// Will try to get an avaible item out of the pool
+ /// If there is no item avaible, this function will block the thread and retry
+ ///
+ /// The item
+ public T getItem()
+ {
+ do{
+ T item;
+ bool popped = pool.TryPop(out item);
+
+ if (pool.Count < increaseBuffer) // less than 'buffer'-amount of items avaiaible
+ {
+ Task.Run(() => createNewObjects(batch)); // Start generating new ones
+ }
+ if (pool.Count > decreaseBuffer) // more than 'buffer'-amount of items avaiaible
+ {
+ Task.Run(() => decrease()); // run decease check
+ }
+
+ if (popped)
+ {
+ if (healthChecker(item)) // Check for item-health
+ {
+ return item; // Item is healthy, return it
+ }
+ else
+ {
+ Task.Run(() => {
+ destruct(item); // Item is not healthy, destruct it
+ createNewObjects(1); // Create new one
+ });
+
+ popped = false;
+ }
+ }
+
+ // No item or healthCheck failed
+ Thread.Sleep(1); // Block the current thread for short time
+
+ } while (true); // retry infinite
+
+ }
+
+ private void createNewObjects(int size)
+ {
+ // create 'size'-amount of items, as long we dont hit our maximum
+ for (int i = 0; i < size && current < max; i++)
+ {
+ // create new item
+ T item = create();
+ // add new item to the pool
+ pool.Push(item);
+ }
+ }
+
+ private T create()
+ {
+ // Try to run create-method
+ T item;
+ try
+ {
+ current++;
+ item = creator();
+
+ // Check if create-delegate returned a null-reference
+ if (item == null)
+ {
+ throw new NullReferenceException("Creator-delegate returned 'null'-reference!");
+ }
+ else
+ {
+ return item;
+ }
+ }
+ catch (Exception ex)
+ {
+ current--;
+ throw new Exception($"Error while creating new '{typeof(T).ToString()}'", ex);
+ }
+ }
+
+ private void decrease()
+ {
+ if (pool.Count > decreaseBuffer + min)
+ {
+ for (int i = 0; i < pool.Count - decreaseBuffer - min; i++)
+ {
+ T item;
+ bool popped = pool.TryPop(out item);
+ if (popped)
+ {
+ // Run descructor-method with item
+ destruct(item);
+ }
+ }
+ }
+ }
+
+ private void destruct(T item)
+ {
+ // decrease counter
+ current--;
+ // Destruct it
+ destructor(item);
+ }
+
+ ///
+ /// Execute an function-task with an item of the pool
+ /// Will get an item out of the pool, run the and then return it to the pool.
+ ///
+ /// Task to run
+ public U Exec(Func task)
+ {
+ T item = getItem(); // Get item from stack
+
+ try
+ {
+ return task(item); // Run task with item and return result
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"Error while executing task with '{typeof(T).ToString()}'", ex);
+ }
+ finally
+ {
+ pool.Push(item); // Put it back to the stack
+ Task.Run(() => decrease()); // Run decrease check
+ }
+ }
+
+ ///
+ /// Execute an action-task with an item of the pool
+ /// Will get an item out of the pool, run the and then return it to the pool.
+ ///
+ /// Task to run
+ public void Exec(Action task)
+ {
+ T item = getItem(); // Get item from stack
+
+ try
+ {
+ task(item); // Run my task with item
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"Error while executing task with '{typeof(T).ToString()}'", ex);
+ }
+ finally
+ {
+ pool.Push(item); // Put it back to the stack
+ Task.Run(() => decrease()); // Run decrease check
+ }
+ }
+ }
+}