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