Projektdateien hinzufügen.
This commit is contained in:
parent
9ff9e6871e
commit
3c47cbc703
25
ManagedPool.sln
Normal file
25
ManagedPool.sln
Normal file
@ -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
|
13
ManagedPool/ManagedPool.csproj
Normal file
13
ManagedPool/ManagedPool.csproj
Normal file
@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<RootNamespace>eu.railduction.netcore.dll.ManagedPool</RootNamespace>
|
||||
<Version>1.1.0</Version>
|
||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||
<DelaySign>true</DelaySign>
|
||||
<AssemblyOriginatorKeyFile>eu.railduction_assembly-key.pfx</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
269
ManagedPool/Pool_T_.cs
Normal file
269
ManagedPool/Pool_T_.cs
Normal file
@ -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<T> where T : class
|
||||
{
|
||||
private Func<T> creator;
|
||||
/// <summary>Method to handle item-spawning (needs to return the item-type)</summary>
|
||||
public Func<T> Creator { get => creator; set => creator = value; }
|
||||
|
||||
private Func<T, bool> healthChecker = (T) => { return true; };
|
||||
/// <summary>Method to handle item-health-checking (useful for unstable items)
|
||||
/// <para/>While running the health-check, the Thread will be blocked!</summary>
|
||||
public Func<T, bool> HealthChecker { get => healthChecker; set => healthChecker = value; }
|
||||
|
||||
private Action<T> destructor;
|
||||
/// <summary>Method to handle item-deleting/killing (needs to take the item-type as parameter)</summary>
|
||||
public Action<T> Destructor { get => destructor; set => destructor = value; }
|
||||
|
||||
private ConcurrentStack<T> pool = new ConcurrentStack<T>();
|
||||
private int current = 0, max = 100, min = 10, batch = 5, increaseBuffer = 5, decreaseBuffer = 10;
|
||||
|
||||
/// <summary>The current amount of items in the pool</summary>
|
||||
public int Current { get => min; }
|
||||
/// <summary>The current amount of items avaiaible in the pool</summary>
|
||||
public int CurrentAvaiaible { get => pool.Count; }
|
||||
|
||||
/// <summary>The minimum amount of items in the pool</summary>
|
||||
public int Min { get => min; set => min = value; }
|
||||
/// <summary>The maximum amount of items in the pool</summary>
|
||||
public int Max { get => max; set => max = value; }
|
||||
/// <summary>Amount if items being spawned at a time if needed</summary>
|
||||
public int Batch { get => batch; set => batch = value; }
|
||||
/// <summary>If less items are in the pool that the buffer, it will spawn 'batch'-amount</summary>
|
||||
public int IncreaseBuffer { get => increaseBuffer; set => increaseBuffer = value; }
|
||||
/// <summary>If more items are in the pool that the buffer, it will delete/kill the overflowing items</summary>
|
||||
public int DecreaseBuffer { get => decreaseBuffer; set => decreaseBuffer = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a managed pool<para/>
|
||||
/// Will automatically spawn <paramref name="min"/> items
|
||||
/// </summary>
|
||||
/// <param name="min">The minimum amount of items in the pool</param>
|
||||
/// <param name="max">The maximum amount of items in the pool</param>
|
||||
/// <param name="batch">Amount if items being spawned at a time if needed</param>
|
||||
/// <param name="increaseBuffer">If less items are in the pool than the <paramref name="increaseBuffer"/>, it will spawn <paramref name="batch"/>-amount</param>
|
||||
/// <param name="decreaseBuffer">If more items are in the pool than the <paramref name="decreaseBuffer"/>, it will delete/kill the overflowing items</param>
|
||||
/// <param name="creator">Method to handle item-spawning (needs to return the item-type)</param>
|
||||
/// <param name="destructor">Method to handle item-deleting/killing (needs to take the item-type as parameter)</param>
|
||||
public Pool(int min, int max, int batch, int increaseBuffer, int decreaseBuffer, Func<T> creator, Action<T> 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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a managed pool<para/>
|
||||
/// Will automatically spawn <paramref name="min"/> items<para/>
|
||||
/// The health-check is run before an item is used for execution
|
||||
/// </summary>
|
||||
/// <param name="min">The minimum amount of items in the pool</param>
|
||||
/// <param name="max">The maximum amount of items in the pool</param>
|
||||
/// <param name="batch">Amount if items being spawned at a time if needed</param>
|
||||
/// <param name="increaseBuffer">If less items are in the pool than the <paramref name="increaseBuffer"/>, it will spawn <paramref name="batch"/>-amount</param>
|
||||
/// <param name="decreaseBuffer">If more items are in the pool than the <paramref name="decreaseBuffer"/>, it will delete/kill the overflowing items</param>
|
||||
/// <param name="creator">Method to handle item-spawning</param>
|
||||
/// <param name="destructor">Method to handle item-deleting/killing</param>
|
||||
/// <param name="healthChecker">Method to handle item-health-checking (useful for unstable items)
|
||||
/// <para/>While running the health-check, the Thread will be blocked!</param>
|
||||
public Pool(int min, int max, int batch, int increaseBuffer, int decreaseBuffer, Func<T> creator, Action<T> destructor, Func<T, bool> 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'!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
/// <returns>The item</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute an function-task with an item of the pool<para/>
|
||||
/// Will get an item out of the pool, run the <paramref name="task"/> and then return it to the pool.
|
||||
/// </summary>
|
||||
/// <param name="task">Task to run</param>
|
||||
public U Exec<U>(Func<T, U> 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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute an action-task with an item of the pool<para/>
|
||||
/// Will get an item out of the pool, run the <paramref name="task"/> and then return it to the pool.
|
||||
/// </summary>
|
||||
/// <param name="task">Task to run</param>
|
||||
public void Exec(Action<T> 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user