mirror of
https://github.com/farcasclaudiu/SmartThreadPool.git
synced 2026-06-22 09:01:19 +03:00
v1.0
SmartThreadPool v1.0
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
||||
@@ -0,0 +1,225 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
/*
|
||||
* The code below generates permutations.
|
||||
*
|
||||
* The original code was written by Michael Gilleland,
|
||||
* and can be found in the following site
|
||||
* http://www.merriampark.com/perm.htm
|
||||
*
|
||||
* I translated it to C# from Java.
|
||||
*/
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
//--------------------------------------
|
||||
// Systematically generate permutations.
|
||||
//--------------------------------------
|
||||
|
||||
public class PermutationGenerator : IEnumerable
|
||||
{
|
||||
private object [] _objects;
|
||||
|
||||
public PermutationGenerator(object [] objects)
|
||||
{
|
||||
_objects = (object [])objects.Clone();
|
||||
}
|
||||
|
||||
#region IEnumerable Members
|
||||
|
||||
public IEnumerator GetEnumerator()
|
||||
{
|
||||
return new PermutationGeneratorEnumerator(_objects);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private class PermutationGeneratorEnumerator : IEnumerator
|
||||
{
|
||||
private object [] _objects;
|
||||
private object [] _currentPermutation;
|
||||
private PermutationGeneratorHelper _permutationGeneratorHelper;
|
||||
|
||||
public PermutationGeneratorEnumerator(object [] objects)
|
||||
{
|
||||
_objects = objects;
|
||||
Reset();
|
||||
}
|
||||
|
||||
#region IEnumerator Members
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_permutationGeneratorHelper = new PermutationGeneratorHelper(_objects.Length);
|
||||
}
|
||||
|
||||
public object Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return _currentPermutation;
|
||||
}
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_permutationGeneratorHelper.hasMore())
|
||||
{
|
||||
_currentPermutation = new object[_objects.Length];
|
||||
int [] indices = _permutationGeneratorHelper.getNext();
|
||||
for (int i = 0; i < indices.Length; i++)
|
||||
{
|
||||
_currentPermutation[i] = _objects[indices[i]];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
_currentPermutation = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
private class PermutationGeneratorHelper
|
||||
{
|
||||
|
||||
private int[] a;
|
||||
private long numLeft;
|
||||
private long total;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Constructor. WARNING: Don't make n too large.
|
||||
// Recall that the number of permutations is n!
|
||||
// which can be very large, even when n is as small as 20 --
|
||||
// 20! = 2,432,902,008,176,640,000 and
|
||||
// 21! is too big to fit into a Java long, which is
|
||||
// why we use long instead.
|
||||
//----------------------------------------------------------
|
||||
|
||||
public PermutationGeneratorHelper (int n)
|
||||
{
|
||||
if (n < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("n", n, "Min 1");
|
||||
}
|
||||
a = new int[n];
|
||||
total = getFactorial (n);
|
||||
reset();
|
||||
}
|
||||
|
||||
//------
|
||||
// Reset
|
||||
//------
|
||||
|
||||
public void reset ()
|
||||
{
|
||||
for (int i = 0; i < a.Length; i++)
|
||||
{
|
||||
a[i] = i;
|
||||
}
|
||||
numLeft = total;
|
||||
}
|
||||
|
||||
//------------------------------------------------
|
||||
// Return number of permutations not yet generated
|
||||
//------------------------------------------------
|
||||
|
||||
public long getNumLeft ()
|
||||
{
|
||||
return numLeft;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
// Return total number of permutations
|
||||
//------------------------------------
|
||||
|
||||
public long getTotal ()
|
||||
{
|
||||
return total;
|
||||
}
|
||||
|
||||
//-----------------------------
|
||||
// Are there more permutations?
|
||||
//-----------------------------
|
||||
|
||||
public bool hasMore ()
|
||||
{
|
||||
return (numLeft > 0);
|
||||
}
|
||||
|
||||
//------------------
|
||||
// Compute factorial
|
||||
//------------------
|
||||
|
||||
private static long getFactorial (int n)
|
||||
{
|
||||
long fact = 1;
|
||||
for (int i = n; i > 1; i--)
|
||||
{
|
||||
fact = fact * i;
|
||||
}
|
||||
return fact;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Generate next permutation (algorithm from Rosen p. 284)
|
||||
//--------------------------------------------------------
|
||||
|
||||
public int[] getNext ()
|
||||
{
|
||||
|
||||
if (numLeft == total)
|
||||
{
|
||||
--numLeft;
|
||||
return a;
|
||||
}
|
||||
|
||||
int temp;
|
||||
|
||||
// Find largest index j with a[j] < a[j+1]
|
||||
|
||||
int j = a.Length - 2;
|
||||
while (a[j] > a[j+1])
|
||||
{
|
||||
j--;
|
||||
}
|
||||
|
||||
// Find index k such that a[k] is smallest integer
|
||||
// greater than a[j] to the right of a[j]
|
||||
|
||||
int k = a.Length - 1;
|
||||
while (a[j] > a[k])
|
||||
{
|
||||
k--;
|
||||
}
|
||||
|
||||
// Interchange a[j] and a[k]
|
||||
|
||||
temp = a[k];
|
||||
a[k] = a[j];
|
||||
a[j] = temp;
|
||||
|
||||
// Put tail end of permutation after jth position in increasing order
|
||||
|
||||
int r = a.Length - 1;
|
||||
int s = j + 1;
|
||||
|
||||
while (r > s)
|
||||
{
|
||||
temp = a[s];
|
||||
a[s] = a[r];
|
||||
a[r] = temp;
|
||||
r--;
|
||||
s++;
|
||||
}
|
||||
|
||||
--numLeft;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ApplicationIcon>
|
||||
</ApplicationIcon>
|
||||
<AssemblyKeyContainerName>
|
||||
</AssemblyKeyContainerName>
|
||||
<AssemblyName>STPTests</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>
|
||||
</AssemblyOriginatorKeyFile>
|
||||
<DefaultClientScript>JScript</DefaultClientScript>
|
||||
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
||||
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
||||
<DelaySign>false</DelaySign>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>STPTests</RootNamespace>
|
||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>false</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>true</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>none</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="nunit.framework, Version=2.2.5.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Data">
|
||||
<Name>System.Data</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml">
|
||||
<Name>System.XML</Name>
|
||||
</Reference>
|
||||
<ProjectReference Include="..\SmartThreadPool\SmartThreadPool.csproj">
|
||||
<Name>SmartThreadPool</Name>
|
||||
<Project>{8684FC56-A679-4E2E-8F96-E172FB062EB6}</Project>
|
||||
<Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PermutationGenerator.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestChainedDelegates.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestExceptions.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestGetResult.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestMultipleWorkItems.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestPostExecute.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestPriorityQueue.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestStartSuspended.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestStateDispose.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestThreadPriority.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestWaitForIdle.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestWIGChainedDelegates.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestWIGConcurrency.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestWIGExceptions.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestWIGGetResult.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestWIGMultipleWorkItems.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestWIGPostExecute.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestWIGStateDispose.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestWIGWaitForIdle.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestWorkItemsGroups.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestWorkItemsQueue.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestChainedDelegates.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestChainedDelegates")]
|
||||
public class TestChainedDelegates
|
||||
{
|
||||
public TestChainedDelegates()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GoodCallback()
|
||||
{
|
||||
SmartThreadPool stp = new SmartThreadPool();
|
||||
|
||||
stp.QueueWorkItem(new WorkItemCallback(DoWork));
|
||||
|
||||
stp.WaitForIdle();
|
||||
|
||||
stp.Shutdown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(NotSupportedException))]
|
||||
public void ChainedDelegatesCallback()
|
||||
{
|
||||
SmartThreadPool stp = new SmartThreadPool();
|
||||
|
||||
WorkItemCallback workItemCallback = new WorkItemCallback(DoWork);
|
||||
workItemCallback += new WorkItemCallback(DoWork);
|
||||
|
||||
stp.QueueWorkItem(workItemCallback);
|
||||
|
||||
stp.WaitForIdle();
|
||||
|
||||
stp.Shutdown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GoodPostExecute()
|
||||
{
|
||||
SmartThreadPool stp = new SmartThreadPool();
|
||||
|
||||
stp.QueueWorkItem(
|
||||
new WorkItemCallback(DoWork),
|
||||
null,
|
||||
new PostExecuteWorkItemCallback(DoPostExecute));
|
||||
|
||||
stp.WaitForIdle();
|
||||
|
||||
stp.Shutdown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(NotSupportedException))]
|
||||
public void ChainedDelegatesPostExecute()
|
||||
{
|
||||
SmartThreadPool stp = new SmartThreadPool();
|
||||
|
||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback =
|
||||
new PostExecuteWorkItemCallback(DoPostExecute);
|
||||
postExecuteWorkItemCallback +=
|
||||
new PostExecuteWorkItemCallback(DoPostExecute);
|
||||
|
||||
stp.QueueWorkItem(
|
||||
new WorkItemCallback(DoWork),
|
||||
null,
|
||||
postExecuteWorkItemCallback);
|
||||
|
||||
stp.WaitForIdle();
|
||||
|
||||
stp.Shutdown();
|
||||
}
|
||||
|
||||
|
||||
private object DoWork(object state)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private void DoPostExecute(IWorkItemResult wir)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestExceptions.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestExceptions")]
|
||||
public class TestExceptions
|
||||
{
|
||||
private class DivArgs
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrowing()
|
||||
{
|
||||
SmartThreadPool _smartThreadPool = new SmartThreadPool();
|
||||
|
||||
DivArgs divArgs = new DivArgs();
|
||||
divArgs.x = 10;
|
||||
divArgs.y = 0;
|
||||
|
||||
IWorkItemResult wir =
|
||||
_smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoDiv), divArgs);
|
||||
|
||||
try
|
||||
{
|
||||
wir.GetResult();
|
||||
}
|
||||
catch(WorkItemResultException wire)
|
||||
{
|
||||
Assert.IsTrue(wire.InnerException is DivideByZeroException);
|
||||
return;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.GetHashCode();
|
||||
Assert.Fail();
|
||||
}
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionReturning()
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
SmartThreadPool _smartThreadPool = new SmartThreadPool();
|
||||
|
||||
DivArgs divArgs = new DivArgs();
|
||||
divArgs.x = 10;
|
||||
divArgs.y = 0;
|
||||
|
||||
IWorkItemResult wir =
|
||||
_smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoDiv), divArgs);
|
||||
|
||||
Exception e = null;
|
||||
try
|
||||
{
|
||||
wir.GetResult(out e);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.GetHashCode();
|
||||
success = false;
|
||||
}
|
||||
|
||||
Assert.IsTrue(success);
|
||||
Assert.IsTrue(e is DivideByZeroException);
|
||||
}
|
||||
|
||||
private object DoDiv(object state)
|
||||
{
|
||||
DivArgs divArgs = (DivArgs)state;
|
||||
return (divArgs.x / divArgs.y);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for GetResultExample.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestGetResult")]
|
||||
public class TestGetResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Example of how to queue a work item and then wait infinitely for the result.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void BlockingCall()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
bool success = false;
|
||||
|
||||
IWorkItemResult wir =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
if (!wir.IsCompleted)
|
||||
{
|
||||
int result = (int)wir.GetResult();
|
||||
success = (1 == result);
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue a work item and then wait on a timeout for the result.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Timeout()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
bool success = false;
|
||||
|
||||
IWorkItemResult wir =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
try
|
||||
{
|
||||
wir.GetResult(500, true);
|
||||
}
|
||||
catch (WorkItemTimeoutException)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue a work item and then cancel it while it is in the queue.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WorkItemCanceling()
|
||||
{
|
||||
// Create a SmartThreadPool with only one thread.
|
||||
// It just to show how to use the work item canceling feature
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 1);
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Queue a work item that will occupy the thread in the pool
|
||||
IWorkItemResult wir1 =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
// Queue another work item that will wait for the first to complete
|
||||
IWorkItemResult wir2 =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
// Wait a while for the thread pool to start executing the first work item
|
||||
Thread.Sleep(100);
|
||||
|
||||
// The first work item cannot be canceled since it is currently executing
|
||||
if (!wir1.Cancel())
|
||||
{
|
||||
// Cancel the second work item while it still in the queue
|
||||
if (wir2.Cancel())
|
||||
{
|
||||
try
|
||||
{
|
||||
// Retreiving result of a canceled work item throws an exception
|
||||
wir2.GetResult();
|
||||
}
|
||||
catch (WorkItemCancelException)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to interrupt the waiting for a work item to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WorkItemWaitCanceling()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
ManualResetEvent cancelWaitHandle = new ManualResetEvent(false);
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Queue a work item that will occupy the thread in the pool
|
||||
IWorkItemResult wir1 =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
// Queue another work item that will wait for the first to complete
|
||||
IWorkItemResult wir2 =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.SignalCancel), cancelWaitHandle);
|
||||
|
||||
try
|
||||
{
|
||||
wir1.GetResult(System.Threading.Timeout.Infinite, true, cancelWaitHandle);
|
||||
}
|
||||
catch (WorkItemTimeoutException)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue a work item and then cancel it while it is in the queue.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WorkItemCancelingAndInUseWorkerThreads()
|
||||
{
|
||||
// Create a SmartThreadPool with only one thread.
|
||||
// It just to show how to use the work item canceling feature
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 10);
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[100];
|
||||
for(int i = 0; i < 100; ++i)
|
||||
{
|
||||
wirs[i] = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
|
||||
// Wait a while for the thread pool to start executing the first work item
|
||||
Thread.Sleep(100);
|
||||
|
||||
for(int i = 0; i < 100; ++i)
|
||||
{
|
||||
wirs[i].Cancel();
|
||||
}
|
||||
|
||||
smartThreadPool.WaitForIdle(2000);
|
||||
|
||||
int inUseThreads = smartThreadPool.InUseThreads;
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.AreEqual(0, inUseThreads);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private object SignalCancel(object state)
|
||||
{
|
||||
ManualResetEvent cancelWaitHandle = state as ManualResetEvent;
|
||||
Thread.Sleep(250);
|
||||
cancelWaitHandle.Set();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for MultipleWorkItemsExample.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestMultipleWorkItems")]
|
||||
public class TestMultipleWorkItems
|
||||
{
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait infinitely for
|
||||
/// all of them to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAll()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
bool success = true;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
SmartThreadPool.WaitAll(wirs);
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
if (!wirs[i].IsCompleted)
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
int result = (int)wirs[i].GetResult();
|
||||
if (1 != result)
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait infinitely for
|
||||
/// one of them to complete.
|
||||
///
|
||||
/// You can use this technique if you have several work items that return the same
|
||||
/// infomration, but use different method to aquire it. Just execute all of them at
|
||||
/// once and wait for the first work item to complete.
|
||||
///
|
||||
/// For example: You need an information about a person and you can query several
|
||||
/// information sites (FBI, CIA, etc.). Query all of them at once and use the first
|
||||
/// answer to arrive.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAny()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
bool success = false;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
int index = SmartThreadPool.WaitAny(wirs);
|
||||
|
||||
if (wirs[index].IsCompleted)
|
||||
{
|
||||
int result = (int)wirs[index].GetResult();
|
||||
if (1 == result)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait on a timeout for all
|
||||
/// of them to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAllWithTimeoutSuccess()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
bool success = true;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
bool timeout = !SmartThreadPool.WaitAll(wirs, 1500, true);
|
||||
success = !timeout;
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait on a timeout for all
|
||||
/// of them to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAllWithTimeoutFailure()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
bool success = true;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
bool timeout = !SmartThreadPool.WaitAll(wirs, 10, true);
|
||||
success = timeout;
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait on a timeout for any
|
||||
/// of them to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAnyWithTimeoutSuccess()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
bool success = true;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
int index = SmartThreadPool.WaitAny(wirs, 1500, true);
|
||||
|
||||
success = (index != WaitHandle.WaitTimeout);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait on a timeout for any
|
||||
/// of them to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAnyWithTimeoutFailure()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
bool success = true;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
int index = SmartThreadPool.WaitAny(wirs, 10, true);
|
||||
|
||||
success = (index == WaitHandle.WaitTimeout);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WaitAllWithEmptyArray()
|
||||
{
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[0];
|
||||
|
||||
bool success = SmartThreadPool.WaitAll(wirs);;
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for DoTestPostExecute.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("DoTestPostExecute")]
|
||||
public class TestPostExecution
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void DefaultPostExecute_AlwaysCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.Always, true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultPostExecute_NeverCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.Never, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultPostExecute_CallWhenCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.WhenWorkItemCanceled, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultPostExecute_CallWhenNotCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.WhenWorkItemNotCanceled, true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void PostExecute_AlwaysCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecute(CallToPostExecute.Always, true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecute_NeverCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecute(CallToPostExecute.Never, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecute_CallWhenCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecute(CallToPostExecute.WhenWorkItemCanceled, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecute_CallWhenNotCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecute(CallToPostExecute.WhenWorkItemNotCanceled, true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void PostExecuteWithCancel_AlwaysCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.Always, true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecuteWithCancel_NeverCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.Never, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecuteWithCancel_CallWhenCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.WhenWorkItemCanceled, true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecuteWithCancel_CallWhenNotCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.WhenWorkItemNotCanceled, false));
|
||||
}
|
||||
|
||||
|
||||
private class PostExecuteResult
|
||||
{
|
||||
public ManualResetEvent wh = new ManualResetEvent(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to use the post execute callback
|
||||
/// </summary>
|
||||
private bool DoTestDefaultPostExecute(CallToPostExecute callToPostExecute, bool answer)
|
||||
{
|
||||
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||
stpStartInfo.CallToPostExecute = callToPostExecute;
|
||||
stpStartInfo.PostExecuteWorkItemCallback = new PostExecuteWorkItemCallback(this.DoSomePostExecuteWork);
|
||||
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(stpStartInfo);
|
||||
|
||||
bool success = false;
|
||||
|
||||
PostExecuteResult postExecuteResult = new PostExecuteResult();
|
||||
|
||||
IWorkItemResult wir =
|
||||
smartThreadPool.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
postExecuteResult);
|
||||
|
||||
if (!wir.IsCompleted)
|
||||
{
|
||||
int result = (int)wir.GetResult();
|
||||
success = (1 == result);
|
||||
success = success && (postExecuteResult.wh.WaitOne(1000, true) == answer);
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to use the post execute callback
|
||||
/// </summary>
|
||||
private bool DoTestPostExecute(CallToPostExecute callToPostExecute, bool answer)
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
bool success = false;
|
||||
|
||||
PostExecuteResult postExecuteResult = new PostExecuteResult();
|
||||
|
||||
IWorkItemResult wir =
|
||||
smartThreadPool.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
postExecuteResult,
|
||||
new PostExecuteWorkItemCallback(this.DoSomePostExecuteWork),
|
||||
callToPostExecute);
|
||||
|
||||
if (!wir.IsCompleted)
|
||||
{
|
||||
int result = (int)wir.GetResult();
|
||||
success = (1 == result);
|
||||
success = success && (postExecuteResult.wh.WaitOne(1000, true) == answer);
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue a work item and then cancel it while it is in the queue.
|
||||
/// </summary>
|
||||
private bool DoTestPostExecuteWithCancel(CallToPostExecute callToPostExecute, bool answer)
|
||||
{
|
||||
// Create a SmartThreadPool with only one thread.
|
||||
// It just to show how to use the work item canceling feature
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 1);
|
||||
|
||||
bool success = false;
|
||||
PostExecuteResult postExecuteResult = new PostExecuteResult();
|
||||
|
||||
// Queue a work item that will occupy the thread in the pool
|
||||
smartThreadPool.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
null);
|
||||
|
||||
// Queue another work item that will wait for the first to complete
|
||||
IWorkItemResult wir =
|
||||
smartThreadPool.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
postExecuteResult,
|
||||
new PostExecuteWorkItemCallback(this.DoSomePostExecuteWork),
|
||||
callToPostExecute);
|
||||
|
||||
|
||||
// Wait a while for the thread pool to start executing the first work item
|
||||
Thread.Sleep(100);
|
||||
|
||||
// Cancel the second work item while it still in the queue
|
||||
if (wir.Cancel())
|
||||
{
|
||||
success = (postExecuteResult.wh.WaitOne(1000, true) == answer);
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private void DoSomePostExecuteWork(IWorkItemResult wir)
|
||||
{
|
||||
PostExecuteResult postExecuteResult = wir.State as PostExecuteResult;
|
||||
postExecuteResult.wh.Set();
|
||||
}
|
||||
|
||||
private object SignalCancel(object state)
|
||||
{
|
||||
ManualResetEvent cancelWaitHandle = state as ManualResetEvent;
|
||||
Thread.Sleep(250);
|
||||
cancelWaitHandle.Set();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
using System;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
using Amib.Threading.Internal;
|
||||
using SmartThreadPoolTests;
|
||||
|
||||
namespace PriorityQueueTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestPriorityQueue.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestPriorityQueue")]
|
||||
public class TestPriorityQueue
|
||||
{
|
||||
public TestPriorityQueue()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Init()
|
||||
{
|
||||
PriorityQueue pq = new PriorityQueue();
|
||||
|
||||
Assert.AreEqual(0, pq.Count);
|
||||
|
||||
Assert.IsNull(pq.Dequeue());
|
||||
|
||||
Assert.AreEqual(0, pq.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OneWorkItem()
|
||||
{
|
||||
WorkItemPriority [] priorities = Enum.GetValues(typeof(WorkItemPriority)) as WorkItemPriority [];
|
||||
foreach(WorkItemPriority wip in priorities)
|
||||
{
|
||||
PriorityQueue pq = new PriorityQueue();
|
||||
|
||||
PriorityItem pi = new PriorityItem(wip);
|
||||
|
||||
pq.Enqueue(pi);
|
||||
|
||||
Assert.AreEqual(1, pq.Count, "Failed for priority {0}", wip);
|
||||
|
||||
PriorityItem pi2 = pq.Dequeue() as PriorityItem;
|
||||
|
||||
Assert.IsNotNull(pi2, "Failed for priority {0}", wip);
|
||||
|
||||
Assert.AreSame(pi, pi2, "Failed for priority {0}", wip);
|
||||
|
||||
Assert.AreEqual(0, pq.Count, "Failed for priority {0}", wip);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MultipleWorkItemsOnePriority()
|
||||
{
|
||||
WorkItemPriority [] priorities = Enum.GetValues(typeof(WorkItemPriority)) as WorkItemPriority [];
|
||||
foreach(WorkItemPriority wip in priorities)
|
||||
{
|
||||
PriorityQueue pq = new PriorityQueue();
|
||||
|
||||
PriorityItem [] priorityItems = new PriorityItem[10];
|
||||
|
||||
for(int i = 0; i < priorityItems.Length; ++i)
|
||||
{
|
||||
priorityItems[i] = new PriorityItem(wip);
|
||||
|
||||
pq.Enqueue(priorityItems[i]);
|
||||
|
||||
Assert.AreEqual(i+1, pq.Count, "Failed for priority {0} item count {1}", wip, i+1);
|
||||
}
|
||||
|
||||
for(int i = 0; i < priorityItems.Length; ++i)
|
||||
{
|
||||
PriorityItem pi = pq.Dequeue() as PriorityItem;
|
||||
|
||||
Assert.AreEqual(priorityItems.Length-(i+1), pq.Count, "Failed for priority {0} item count {1}", wip, i+1);
|
||||
|
||||
Assert.IsNotNull(pi, "Failed for priority {0} item count {1}", wip, i+1);
|
||||
|
||||
Assert.AreSame(pi, priorityItems[i], "Failed for priority {0} item count {1}", wip, i+1);
|
||||
}
|
||||
|
||||
Assert.AreEqual(0, pq.Count, "Failed for priority {0}", wip);
|
||||
|
||||
Assert.IsNull(pq.Dequeue());
|
||||
|
||||
Assert.AreEqual(0, pq.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MultipleWorkItemsMultiplePriorities()
|
||||
{
|
||||
// Get all the available priorities
|
||||
WorkItemPriority [] priorities = Enum.GetValues(typeof(WorkItemPriority)) as WorkItemPriority [];
|
||||
|
||||
// Create an array of priority items
|
||||
PriorityItem [] priorityItems = new PriorityItem[priorities.Length];
|
||||
|
||||
// Create a priority item for each priority
|
||||
int i = priorities.Length;
|
||||
foreach(WorkItemPriority workItemPriority in priorities)
|
||||
{
|
||||
--i;
|
||||
priorityItems[i] = new PriorityItem(workItemPriority);
|
||||
}
|
||||
|
||||
// Create a PermutationGenerator for the priority items
|
||||
PermutationGenerator permutations = new PermutationGenerator(priorityItems);
|
||||
|
||||
int count = 0;
|
||||
// Iterate over the permutations
|
||||
foreach(object [] permutation in permutations)
|
||||
{
|
||||
++count;
|
||||
Console.Write("Permutation #" + count + " : ");
|
||||
for(int j = 0; j < permutation.Length; ++j)
|
||||
{
|
||||
PriorityItem pi = permutation[j] as PriorityItem;
|
||||
Console.Write(pi.WorkItemPriority + ", ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
// Create a priority queue
|
||||
PriorityQueue pq = new PriorityQueue();
|
||||
|
||||
// Enqueue each priority item according to the permutation
|
||||
for(i = 0; i < permutation.Length; ++i)
|
||||
{
|
||||
PriorityItem priorityItem = permutation[i] as PriorityItem;
|
||||
pq.Enqueue(priorityItem);
|
||||
}
|
||||
|
||||
// Make sure all the priority items are in the queue
|
||||
Assert.AreEqual(priorityItems.Length, pq.Count);
|
||||
|
||||
// Compare the order of the priority items
|
||||
for(i = 0; i < priorityItems.Length; ++i)
|
||||
{
|
||||
PriorityItem priorityItem = pq.Dequeue() as PriorityItem;
|
||||
Assert.AreSame(priorityItems[i], priorityItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PriorityItem : IHasWorkItemPriority
|
||||
{
|
||||
private WorkItemPriority _workItemPriority;
|
||||
|
||||
public PriorityItem(WorkItemPriority workItemPriority)
|
||||
{
|
||||
_workItemPriority = workItemPriority;
|
||||
}
|
||||
|
||||
public WorkItemPriority WorkItemPriority
|
||||
{
|
||||
get
|
||||
{
|
||||
return _workItemPriority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestStartSuspended.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestStartSuspended")]
|
||||
public class TestStartSuspended
|
||||
{
|
||||
public TestStartSuspended()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StartSuspended()
|
||||
{
|
||||
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||
stpStartInfo.StartSuspended = true;
|
||||
|
||||
SmartThreadPool stp = new SmartThreadPool(stpStartInfo);
|
||||
|
||||
stp.QueueWorkItem(new WorkItemCallback(this.DoWork));
|
||||
|
||||
Assert.IsFalse(stp.WaitForIdle(200));
|
||||
|
||||
stp.Start();
|
||||
|
||||
Assert.IsTrue(stp.WaitForIdle(200));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WIGStartSuspended()
|
||||
{
|
||||
SmartThreadPool stp = new SmartThreadPool();
|
||||
|
||||
WIGStartInfo wigStartInfo = new WIGStartInfo();
|
||||
wigStartInfo.StartSuspended = true;
|
||||
|
||||
IWorkItemsGroup wig = stp.CreateWorkItemsGroup(10, wigStartInfo);
|
||||
|
||||
wig.QueueWorkItem(new WorkItemCallback(this.DoWork));
|
||||
|
||||
Assert.IsFalse(wig.WaitForIdle(200));
|
||||
|
||||
wig.Start();
|
||||
|
||||
Assert.IsTrue(wig.WaitForIdle(200));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void STPAndWIGStartSuspended()
|
||||
{
|
||||
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||
stpStartInfo.StartSuspended = true;
|
||||
|
||||
SmartThreadPool stp = new SmartThreadPool(stpStartInfo);
|
||||
|
||||
WIGStartInfo wigStartInfo = new WIGStartInfo();
|
||||
wigStartInfo.StartSuspended = true;
|
||||
|
||||
IWorkItemsGroup wig = stp.CreateWorkItemsGroup(10, wigStartInfo);
|
||||
|
||||
wig.QueueWorkItem(new WorkItemCallback(this.DoWork));
|
||||
|
||||
Assert.IsFalse(wig.WaitForIdle(200));
|
||||
|
||||
wig.Start();
|
||||
|
||||
Assert.IsFalse(wig.WaitForIdle(200));
|
||||
|
||||
stp.Start();
|
||||
|
||||
Assert.IsTrue(wig.WaitForIdle(200));
|
||||
Assert.IsTrue(stp.WaitForIdle(0));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void TwoWIGsStartSuspended()
|
||||
{
|
||||
SmartThreadPool stp = new SmartThreadPool();
|
||||
|
||||
WIGStartInfo wigStartInfo = new WIGStartInfo();
|
||||
wigStartInfo.StartSuspended = true;
|
||||
|
||||
IWorkItemsGroup wig1 = stp.CreateWorkItemsGroup(10, wigStartInfo);
|
||||
IWorkItemsGroup wig2 = stp.CreateWorkItemsGroup(10, wigStartInfo);
|
||||
|
||||
wig1.QueueWorkItem(new WorkItemCallback(this.DoWork));
|
||||
wig2.QueueWorkItem(new WorkItemCallback(this.DoWork));
|
||||
|
||||
Assert.IsFalse(wig1.WaitForIdle(200));
|
||||
Assert.IsFalse(wig2.WaitForIdle(200));
|
||||
|
||||
wig1.Start();
|
||||
|
||||
Assert.IsTrue(wig1.WaitForIdle(200));
|
||||
Assert.IsFalse(wig2.WaitForIdle(200));
|
||||
|
||||
wig2.Start();
|
||||
|
||||
Assert.IsTrue(wig1.WaitForIdle(0));
|
||||
Assert.IsTrue(wig2.WaitForIdle(200));
|
||||
}
|
||||
|
||||
|
||||
private object DoWork(object state)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
public class CallerState
|
||||
{
|
||||
private int _val = 0;
|
||||
|
||||
public int Value
|
||||
{
|
||||
get { return _val; }
|
||||
}
|
||||
|
||||
protected void IncValue()
|
||||
{
|
||||
++_val;
|
||||
}
|
||||
}
|
||||
|
||||
public class NonDisposableCallerState : CallerState
|
||||
{
|
||||
public NonDisposableCallerState()
|
||||
{
|
||||
IncValue();
|
||||
}
|
||||
}
|
||||
|
||||
public class DisposableCallerState : CallerState, IDisposable
|
||||
{
|
||||
public DisposableCallerState()
|
||||
{
|
||||
IncValue();
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IncValue();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Summary description for StateDisposeExample.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestStateDispose")]
|
||||
public class TestStateDispose
|
||||
{
|
||||
public TestStateDispose()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of non disposable caller state
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void DisposeCallerState()
|
||||
{
|
||||
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||
stpStartInfo.DisposeOfStateObjects = true;
|
||||
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(stpStartInfo);
|
||||
|
||||
CallerState nonDisposableCallerState = new NonDisposableCallerState();
|
||||
CallerState disposableCallerState = new DisposableCallerState();
|
||||
|
||||
IWorkItemResult wir1 =
|
||||
smartThreadPool.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
nonDisposableCallerState);
|
||||
|
||||
IWorkItemResult wir2 =
|
||||
smartThreadPool.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
disposableCallerState);
|
||||
|
||||
wir1.GetResult();
|
||||
Assert.AreEqual(1, nonDisposableCallerState.Value);
|
||||
|
||||
wir2.GetResult();
|
||||
|
||||
// Wait a little bit for the working thread to call dispose on the
|
||||
// work item's state.
|
||||
smartThreadPool.WaitForIdle();
|
||||
|
||||
Assert.AreEqual(2, disposableCallerState.Value);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of non disposable caller state
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void DontDisposeCallerState()
|
||||
{
|
||||
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||
stpStartInfo.DisposeOfStateObjects = false;
|
||||
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(stpStartInfo);
|
||||
|
||||
bool success = false;
|
||||
|
||||
CallerState nonDisposableCallerState = new NonDisposableCallerState();
|
||||
CallerState disposableCallerState = new DisposableCallerState();
|
||||
|
||||
IWorkItemResult wir1 =
|
||||
smartThreadPool.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
nonDisposableCallerState);
|
||||
|
||||
IWorkItemResult wir2 =
|
||||
smartThreadPool.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
disposableCallerState);
|
||||
|
||||
wir1.GetResult();
|
||||
success = (1 == nonDisposableCallerState.Value);
|
||||
|
||||
wir2.GetResult();
|
||||
|
||||
success = success && (1 == disposableCallerState.Value);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestThreadPriority.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestThreadPriority")]
|
||||
public class TestThreadPriority
|
||||
{
|
||||
[Test]
|
||||
public void TestDefaultPriority()
|
||||
{
|
||||
SmartThreadPool stp = new SmartThreadPool();
|
||||
|
||||
IWorkItemResult wir = stp.QueueWorkItem(new WorkItemCallback(DoSomeWork));
|
||||
ThreadPriority currentThreadPriority = (ThreadPriority)wir.GetResult();
|
||||
|
||||
Assert.AreEqual(currentThreadPriority, SmartThreadPool.DefaultThreadPriority);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPriorities()
|
||||
{
|
||||
ThreadPriority [] priorities =
|
||||
{
|
||||
ThreadPriority.Lowest,
|
||||
ThreadPriority.BelowNormal,
|
||||
ThreadPriority.Normal,
|
||||
ThreadPriority.AboveNormal,
|
||||
ThreadPriority.Highest,
|
||||
};
|
||||
|
||||
foreach(ThreadPriority priority in priorities)
|
||||
{
|
||||
CheckSinglePriority(priority);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckSinglePriority(ThreadPriority threadPriority)
|
||||
{
|
||||
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||
stpStartInfo.ThreadPriority = threadPriority;
|
||||
|
||||
SmartThreadPool stp = new SmartThreadPool(stpStartInfo);
|
||||
|
||||
IWorkItemResult wir = stp.QueueWorkItem(new WorkItemCallback(DoSomeWork));
|
||||
ThreadPriority currentThreadPriority = (ThreadPriority)wir.GetResult();
|
||||
|
||||
Assert.AreEqual(currentThreadPriority, threadPriority);
|
||||
}
|
||||
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
return Thread.CurrentThread.Priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace WorkItemsGroupTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestChainedDelegates.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("Test WorkItemsGroup ChainedDelegates")]
|
||||
public class TestChainedDelegates
|
||||
{
|
||||
public TestChainedDelegates()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GoodCallback()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(DoWork));
|
||||
|
||||
workItemsGroup.WaitForIdle();
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(NotSupportedException))]
|
||||
public void ChainedDelegatesCallback()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
WorkItemCallback workItemCallback = new WorkItemCallback(DoWork);
|
||||
workItemCallback += new WorkItemCallback(DoWork);
|
||||
|
||||
workItemsGroup.QueueWorkItem(workItemCallback);
|
||||
|
||||
workItemsGroup.WaitForIdle();
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GoodPostExecute()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(DoWork),
|
||||
null,
|
||||
new PostExecuteWorkItemCallback(DoPostExecute));
|
||||
|
||||
workItemsGroup.WaitForIdle();
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(NotSupportedException))]
|
||||
public void ChainedDelegatesPostExecute()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback =
|
||||
new PostExecuteWorkItemCallback(DoPostExecute);
|
||||
postExecuteWorkItemCallback +=
|
||||
new PostExecuteWorkItemCallback(DoPostExecute);
|
||||
|
||||
workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(DoWork),
|
||||
null,
|
||||
postExecuteWorkItemCallback);
|
||||
|
||||
workItemsGroup.WaitForIdle();
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
}
|
||||
|
||||
|
||||
private object DoWork(object state)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private void DoPostExecute(IWorkItemResult wir)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestWIGConcurrency.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestWIGConcurrency")]
|
||||
public class TestWIGConcurrency
|
||||
{
|
||||
private Random _randGen;
|
||||
private int [] _concurrentOps;
|
||||
private int _concurrencyPerWig;
|
||||
private bool _success;
|
||||
|
||||
public TestWIGConcurrency()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestConcurrencies()
|
||||
{
|
||||
Concurrency(1, 1, 10);
|
||||
Concurrency(1, 1, 100);
|
||||
|
||||
Concurrency(1, 5, 10);
|
||||
Concurrency(1, 5, 100);
|
||||
|
||||
Concurrency(5, 5, 10);
|
||||
Concurrency(5, 5, 100);
|
||||
}
|
||||
|
||||
private void Concurrency(
|
||||
int concurrencyPerWig,
|
||||
int wigsCount,
|
||||
int workItemsCount)
|
||||
{
|
||||
Console.WriteLine(
|
||||
"Testing : concurrencyPerWig = {0}, wigsCount = {1}, workItemsCount = {2}",
|
||||
concurrencyPerWig,
|
||||
wigsCount,
|
||||
workItemsCount);
|
||||
|
||||
_success = true;
|
||||
_concurrencyPerWig = concurrencyPerWig;
|
||||
_randGen = new Random(0);
|
||||
|
||||
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||
stpStartInfo.StartSuspended = true;
|
||||
|
||||
SmartThreadPool stp = new SmartThreadPool(stpStartInfo);
|
||||
|
||||
_concurrentOps = new int[wigsCount];
|
||||
|
||||
IWorkItemsGroup [] wigs = new IWorkItemsGroup[wigsCount];
|
||||
|
||||
for(int i = 0; i < wigs.Length; ++i)
|
||||
{
|
||||
wigs[i] = stp.CreateWorkItemsGroup(_concurrencyPerWig);
|
||||
for(int j = 0; j < workItemsCount; ++j)
|
||||
{
|
||||
wigs[i].QueueWorkItem(new WorkItemCallback(this.DoWork), i);
|
||||
}
|
||||
|
||||
wigs[i].Start();
|
||||
}
|
||||
|
||||
stp.Start();
|
||||
|
||||
stp.WaitForIdle();
|
||||
|
||||
Assert.IsTrue(_success);
|
||||
|
||||
stp.Shutdown();
|
||||
}
|
||||
|
||||
private object DoWork(object state)
|
||||
{
|
||||
int wigsIndex = (int)state;
|
||||
|
||||
int val = Interlocked.Increment(ref _concurrentOps[wigsIndex]);
|
||||
_success = _success && (val <= _concurrencyPerWig);
|
||||
|
||||
int waitTime = _randGen.Next(50);
|
||||
Thread.Sleep(waitTime);
|
||||
|
||||
val = Interlocked.Decrement(ref _concurrentOps[wigsIndex]);
|
||||
_success = _success && (val >= 0);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace WorkItemsGroupTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestExceptions.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("Test WorkItemsGroup Exceptions")]
|
||||
public class TestExceptions
|
||||
{
|
||||
private class DivArgs
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionThrowing()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
DivArgs divArgs = new DivArgs();
|
||||
divArgs.x = 10;
|
||||
divArgs.y = 0;
|
||||
|
||||
IWorkItemResult wir =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoDiv), divArgs);
|
||||
|
||||
try
|
||||
{
|
||||
wir.GetResult();
|
||||
}
|
||||
catch(WorkItemResultException wire)
|
||||
{
|
||||
Assert.IsTrue(wire.InnerException is DivideByZeroException);
|
||||
return;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.GetHashCode();
|
||||
Assert.Fail();
|
||||
}
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExceptionReturning()
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
DivArgs divArgs = new DivArgs();
|
||||
divArgs.x = 10;
|
||||
divArgs.y = 0;
|
||||
|
||||
IWorkItemResult wir =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoDiv), divArgs);
|
||||
|
||||
Exception e = null;
|
||||
try
|
||||
{
|
||||
wir.GetResult(out e);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.GetHashCode();
|
||||
success = false;
|
||||
}
|
||||
|
||||
Assert.IsTrue(success);
|
||||
Assert.IsTrue(e is DivideByZeroException);
|
||||
}
|
||||
|
||||
private object DoDiv(object state)
|
||||
{
|
||||
DivArgs divArgs = (DivArgs)state;
|
||||
return (divArgs.x / divArgs.y);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace WorkItemsGroupTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for GetResultExample.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("Test WorkItemsGroup GetResult")]
|
||||
public class TestGetResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Example of how to queue a work item and then wait infinitely for the result.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void BlockingCall()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = false;
|
||||
|
||||
IWorkItemResult wir =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
if (!wir.IsCompleted)
|
||||
{
|
||||
int result = (int)wir.GetResult();
|
||||
success = (1 == result);
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue a work item and then wait on a timeout for the result.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Timeout()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = false;
|
||||
|
||||
IWorkItemResult wir =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
try
|
||||
{
|
||||
wir.GetResult(500, true);
|
||||
}
|
||||
catch (WorkItemTimeoutException)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue a work item and then cancel it while it is in the queue.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WorkItemCanceling()
|
||||
{
|
||||
// Create a SmartThreadPool with only one thread.
|
||||
// It just to show how to use the work item canceling feature
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 1);
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Queue a work item that will occupy the thread in the pool
|
||||
IWorkItemResult wir1 =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
// Queue another work item that will wait for the first to complete
|
||||
IWorkItemResult wir2 =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
// Wait a while for the thread pool to start executing the first work item
|
||||
Thread.Sleep(100);
|
||||
|
||||
// The first work item cannot be canceled since it is currently executing
|
||||
if (!wir1.Cancel())
|
||||
{
|
||||
// Cancel the second work item while it still in the queue
|
||||
if (wir2.Cancel())
|
||||
{
|
||||
try
|
||||
{
|
||||
// Retreiving result of a canceled work item throws an exception
|
||||
wir2.GetResult();
|
||||
}
|
||||
catch (WorkItemCancelException)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to interrupt the waiting for a work item to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WorkItemWaitCanceling()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
ManualResetEvent cancelWaitHandle = new ManualResetEvent(false);
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Queue a work item that will occupy the thread in the pool
|
||||
IWorkItemResult wir1 =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
// Queue another work item that will wait for the first to complete
|
||||
IWorkItemResult wir2 =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.SignalCancel), cancelWaitHandle);
|
||||
|
||||
try
|
||||
{
|
||||
wir1.GetResult(System.Threading.Timeout.Infinite, true, cancelWaitHandle);
|
||||
}
|
||||
catch (WorkItemTimeoutException)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private object SignalCancel(object state)
|
||||
{
|
||||
ManualResetEvent cancelWaitHandle = state as ManualResetEvent;
|
||||
Thread.Sleep(250);
|
||||
cancelWaitHandle.Set();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace WorkItemsGroupTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for MultipleWorkItemsExample.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("Test WorkItemsGroup MultipleWorkItems")]
|
||||
public class TestMultipleWorkItems
|
||||
{
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait infinitely for
|
||||
/// all of them to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAll()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = true;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
SmartThreadPool.WaitAll(wirs);
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
if (!wirs[i].IsCompleted)
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
int result = (int)wirs[i].GetResult();
|
||||
if (1 != result)
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait infinitely for
|
||||
/// one of them to complete.
|
||||
///
|
||||
/// You can use this technique if you have several work items that return the same
|
||||
/// infomration, but use different method to aquire it. Just execute all of them at
|
||||
/// once and wait for the first work item to complete.
|
||||
///
|
||||
/// For example: You need an information about a person and you can query several
|
||||
/// information sites (FBI, CIA, etc.). Query all of them at once and use the first
|
||||
/// answer to arrive.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAny()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = false;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
int index = SmartThreadPool.WaitAny(wirs);
|
||||
|
||||
if (wirs[index].IsCompleted)
|
||||
{
|
||||
int result = (int)wirs[index].GetResult();
|
||||
if (1 == result)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait on a timeout for all
|
||||
/// of them to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAllWithTimeoutSuccess()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = true;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
bool timeout = !SmartThreadPool.WaitAll(wirs, 1500, true);
|
||||
success = !timeout;
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait on a timeout for all
|
||||
/// of them to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAllWithTimeoutFailure()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = true;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
bool timeout = !SmartThreadPool.WaitAll(wirs, 10, true);
|
||||
success = timeout;
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait on a timeout for any
|
||||
/// of them to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAnyWithTimeoutSuccess()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = true;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
int index = SmartThreadPool.WaitAny(wirs, 1500, true);
|
||||
|
||||
success = (index != WaitHandle.WaitTimeout);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue several work items and then wait on a timeout for any
|
||||
/// of them to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitAnyWithTimeoutFailure()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = true;
|
||||
|
||||
IWorkItemResult [] wirs = new IWorkItemResult[5];
|
||||
|
||||
for(int i = 0; i < wirs.Length; ++i)
|
||||
{
|
||||
wirs[i] =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
}
|
||||
|
||||
int index = SmartThreadPool.WaitAny(wirs, 10, true);
|
||||
|
||||
success = (index == WaitHandle.WaitTimeout);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace WorkItemsGroupTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for DoTestPostExecute.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("WorkItemsGroup")]
|
||||
public class TestPostExecution
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void DefaultPostExecute_AlwaysCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.Always, true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultPostExecute_NeverCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.Never, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultPostExecute_CallWhenCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.WhenWorkItemCanceled, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DefaultPostExecute_CallWhenNotCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestDefaultPostExecute(CallToPostExecute.WhenWorkItemNotCanceled, true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void PostExecute_AlwaysCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecute(CallToPostExecute.Always, true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecute_NeverCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecute(CallToPostExecute.Never, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecute_CallWhenCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecute(CallToPostExecute.WhenWorkItemCanceled, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecute_CallWhenNotCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecute(CallToPostExecute.WhenWorkItemNotCanceled, true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void PostExecuteWithCancel_AlwaysCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.Always, true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecuteWithCancel_NeverCall()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.Never, false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecuteWithCancel_CallWhenCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.WhenWorkItemCanceled, true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PostExecuteWithCancel_CallWhenNotCanceled()
|
||||
{
|
||||
Assert.IsTrue(DoTestPostExecuteWithCancel(CallToPostExecute.WhenWorkItemNotCanceled, false));
|
||||
}
|
||||
|
||||
|
||||
private class PostExecuteResult
|
||||
{
|
||||
public ManualResetEvent wh = new ManualResetEvent(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to use the post execute callback
|
||||
/// </summary>
|
||||
private bool DoTestDefaultPostExecute(CallToPostExecute callToPostExecute, bool answer)
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
WIGStartInfo wigStartInfo = new WIGStartInfo();
|
||||
wigStartInfo.CallToPostExecute = callToPostExecute;
|
||||
wigStartInfo.PostExecuteWorkItemCallback = new PostExecuteWorkItemCallback(this.DoSomePostExecuteWork);
|
||||
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue, wigStartInfo);
|
||||
|
||||
bool success = false;
|
||||
|
||||
PostExecuteResult postExecuteResult = new PostExecuteResult();
|
||||
|
||||
IWorkItemResult wir =
|
||||
workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
postExecuteResult);
|
||||
|
||||
if (!wir.IsCompleted)
|
||||
{
|
||||
int result = (int)wir.GetResult();
|
||||
success = (1 == result);
|
||||
success = success && (postExecuteResult.wh.WaitOne(1000, true) == answer);
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to use the post execute callback
|
||||
/// </summary>
|
||||
private bool DoTestPostExecute(CallToPostExecute callToPostExecute, bool answer)
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = false;
|
||||
|
||||
PostExecuteResult postExecuteResult = new PostExecuteResult();
|
||||
|
||||
IWorkItemResult wir =
|
||||
workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
postExecuteResult,
|
||||
new PostExecuteWorkItemCallback(this.DoSomePostExecuteWork),
|
||||
callToPostExecute);
|
||||
|
||||
if (!wir.IsCompleted)
|
||||
{
|
||||
int result = (int)wir.GetResult();
|
||||
success = (1 == result);
|
||||
success = success && (postExecuteResult.wh.WaitOne(1000, true) == answer);
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue a work item and then cancel it while it is in the queue.
|
||||
/// </summary>
|
||||
private bool DoTestPostExecuteWithCancel(CallToPostExecute callToPostExecute, bool answer)
|
||||
{
|
||||
// Create a SmartThreadPool with only one thread.
|
||||
// It just to show how to use the work item canceling feature
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(1);
|
||||
|
||||
bool success = false;
|
||||
PostExecuteResult postExecuteResult = new PostExecuteResult();
|
||||
|
||||
// Queue a work item that will occupy the thread in the pool
|
||||
workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
null);
|
||||
|
||||
// Queue another work item that will wait for the first to complete
|
||||
IWorkItemResult wir =
|
||||
workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
postExecuteResult,
|
||||
new PostExecuteWorkItemCallback(this.DoSomePostExecuteWork),
|
||||
callToPostExecute);
|
||||
|
||||
|
||||
// Wait a while for the thread pool to start executing the first work item
|
||||
Thread.Sleep(100);
|
||||
|
||||
// Cancel the second work item while it still in the queue
|
||||
if (wir.Cancel())
|
||||
{
|
||||
success = (postExecuteResult.wh.WaitOne(1000, true) == answer);
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private void DoSomePostExecuteWork(IWorkItemResult wir)
|
||||
{
|
||||
PostExecuteResult postExecuteResult = wir.State as PostExecuteResult;
|
||||
postExecuteResult.wh.Set();
|
||||
}
|
||||
|
||||
private object SignalCancel(object state)
|
||||
{
|
||||
ManualResetEvent cancelWaitHandle = state as ManualResetEvent;
|
||||
Thread.Sleep(250);
|
||||
cancelWaitHandle.Set();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace WorkItemsGroupTests
|
||||
{
|
||||
public class CallerState
|
||||
{
|
||||
private int _val = 0;
|
||||
|
||||
public int Value
|
||||
{
|
||||
get { return _val; }
|
||||
}
|
||||
|
||||
protected void IncValue()
|
||||
{
|
||||
++_val;
|
||||
}
|
||||
}
|
||||
|
||||
public class NonDisposableCallerState : CallerState
|
||||
{
|
||||
public NonDisposableCallerState()
|
||||
{
|
||||
IncValue();
|
||||
}
|
||||
}
|
||||
|
||||
public class DisposableCallerState : CallerState, IDisposable
|
||||
{
|
||||
public DisposableCallerState()
|
||||
{
|
||||
IncValue();
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IncValue();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Summary description for StateDisposeExample.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("WorkItemsGroup")]
|
||||
public class TestStateDispose
|
||||
{
|
||||
public TestStateDispose()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of non disposable caller state
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void DisposeCallerState()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
WIGStartInfo wigStartInfo = new WIGStartInfo();
|
||||
wigStartInfo.DisposeOfStateObjects = true;
|
||||
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue, wigStartInfo);
|
||||
|
||||
CallerState nonDisposableCallerState = new NonDisposableCallerState();
|
||||
CallerState disposableCallerState = new DisposableCallerState();
|
||||
|
||||
IWorkItemResult wir1 =
|
||||
workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
nonDisposableCallerState);
|
||||
|
||||
IWorkItemResult wir2 =
|
||||
workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
disposableCallerState);
|
||||
|
||||
wir1.GetResult();
|
||||
Assert.AreEqual(1, nonDisposableCallerState.Value);
|
||||
|
||||
wir2.GetResult();
|
||||
|
||||
// Wait a little bit for the working thread to call dispose on the
|
||||
// work item's state.
|
||||
workItemsGroup.WaitForIdle();
|
||||
|
||||
Assert.AreEqual(2, disposableCallerState.Value);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of non disposable caller state
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void DontDisposeCallerState()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
|
||||
WIGStartInfo wigStartInfo = new WIGStartInfo();
|
||||
wigStartInfo.DisposeOfStateObjects = false;
|
||||
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue, wigStartInfo);
|
||||
|
||||
bool success = false;
|
||||
|
||||
CallerState nonDisposableCallerState = new NonDisposableCallerState();
|
||||
CallerState disposableCallerState = new DisposableCallerState();
|
||||
|
||||
IWorkItemResult wir1 =
|
||||
workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
nonDisposableCallerState);
|
||||
|
||||
IWorkItemResult wir2 =
|
||||
workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
disposableCallerState);
|
||||
|
||||
wir1.GetResult();
|
||||
success = (1 == nonDisposableCallerState.Value);
|
||||
|
||||
wir2.GetResult();
|
||||
|
||||
success = success && (1 == disposableCallerState.Value);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace WorkItemsGroupTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestWaitForIdle.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("WorkItemsGroup")]
|
||||
public class TestWaitForIdle
|
||||
{
|
||||
public TestWaitForIdle()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of waiting for idle
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitForIdle()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 25, 0);
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = false;
|
||||
|
||||
for(int i = 0; i < 100; ++i)
|
||||
{
|
||||
workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
null);
|
||||
}
|
||||
|
||||
success = !workItemsGroup.WaitForIdle(3500);
|
||||
success = success && workItemsGroup.WaitForIdle(1000);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WaitForIdleOnSTPThread()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 25, 0);
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
IWorkItemResult wir = workItemsGroup.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoWaitForIdle),
|
||||
workItemsGroup);
|
||||
|
||||
Exception e;
|
||||
wir.GetResult(out e);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsNotNull(e);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WaitForIdleOnSTPThreadForAnotherWorkItemsGroup()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 25, 0);
|
||||
IWorkItemsGroup workItemsGroup1 = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
IWorkItemsGroup workItemsGroup2 = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
workItemsGroup1.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
null);
|
||||
|
||||
workItemsGroup1.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
null);
|
||||
|
||||
IWorkItemResult wir = workItemsGroup2.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoWaitForIdle),
|
||||
workItemsGroup1);
|
||||
|
||||
Exception e;
|
||||
wir.GetResult(out e);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsNull(e);
|
||||
}
|
||||
|
||||
|
||||
private int x = 0;
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
Debug.WriteLine(Interlocked.Increment(ref x));
|
||||
Thread.Sleep(1000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private object DoWaitForIdle(object state)
|
||||
{
|
||||
IWorkItemsGroup workItemsGroup = state as IWorkItemsGroup;
|
||||
workItemsGroup.WaitForIdle();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestWaitForIdle.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestWaitForIdle")]
|
||||
public class TestWaitForIdle
|
||||
{
|
||||
public TestWaitForIdle()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of waiting for idle
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WaitForIdle()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 25, 0);
|
||||
|
||||
bool success = false;
|
||||
|
||||
for(int i = 0; i < 100; ++i)
|
||||
{
|
||||
smartThreadPool.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoSomeWork),
|
||||
null);
|
||||
}
|
||||
|
||||
success = !smartThreadPool.WaitForIdle(3500);
|
||||
success = success && smartThreadPool.WaitForIdle(1000);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WaitForIdleOnWrongThread()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 25, 0);
|
||||
|
||||
IWorkItemResult wir = smartThreadPool.QueueWorkItem(
|
||||
new WorkItemCallback(this.DoWaitForIdle),
|
||||
smartThreadPool);
|
||||
|
||||
Exception e;
|
||||
wir.GetResult(out e);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(e is NotSupportedException);
|
||||
}
|
||||
|
||||
|
||||
private int x = 0;
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
Debug.WriteLine(Interlocked.Increment(ref x));
|
||||
Thread.Sleep(1000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private object DoWaitForIdle(object state)
|
||||
{
|
||||
SmartThreadPool smartThreadPool = state as SmartThreadPool;
|
||||
smartThreadPool.WaitForIdle();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace WorkItemsGroupTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestWorkItemsGroups.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestWorkItemsGroups")]
|
||||
public class TestWorkItemsGroups
|
||||
{
|
||||
public TestWorkItemsGroups()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BlockingCall()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = false;
|
||||
|
||||
IWorkItemResult wir =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
if (!wir.IsCompleted)
|
||||
{
|
||||
int result = (int)wir.GetResult();
|
||||
success = (1 == result);
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue a work item and then wait on a timeout for the result.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Timeout()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = false;
|
||||
|
||||
IWorkItemResult wir =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
try
|
||||
{
|
||||
wir.GetResult(500, true);
|
||||
}
|
||||
catch (WorkItemTimeoutException)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to queue a work item and then cancel it while it is in the queue.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WorkItemCanceling()
|
||||
{
|
||||
// Create a SmartThreadPool with only one thread.
|
||||
// It just to show how to use the work item canceling feature
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 1);
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Queue a work item that will occupy the thread in the pool
|
||||
IWorkItemResult wir1 =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
// Queue another work item that will wait for the first to complete
|
||||
IWorkItemResult wir2 =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
// Wait a while for the thread pool to start executing the first work item
|
||||
Thread.Sleep(100);
|
||||
|
||||
// The first work item cannot be canceled since it is currently executing
|
||||
if (!wir1.Cancel())
|
||||
{
|
||||
// Cancel the second work item while it still in the queue
|
||||
if (wir2.Cancel())
|
||||
{
|
||||
try
|
||||
{
|
||||
// Retreiving result of a canceled work item throws an exception
|
||||
wir2.GetResult();
|
||||
}
|
||||
catch (WorkItemCancelException)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Example of how to interrupt the waiting for a work item to complete.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void WorkItemWaitCanceling()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||
|
||||
ManualResetEvent cancelWaitHandle = new ManualResetEvent(false);
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Queue a work item that will occupy the thread in the pool
|
||||
IWorkItemResult wir1 =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||
|
||||
// Queue another work item that will wait for the first to complete
|
||||
IWorkItemResult wir2 =
|
||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.SignalCancel), cancelWaitHandle);
|
||||
|
||||
try
|
||||
{
|
||||
wir1.GetResult(System.Threading.Timeout.Infinite, true, cancelWaitHandle);
|
||||
}
|
||||
catch (WorkItemTimeoutException)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(success);
|
||||
}
|
||||
|
||||
private object DoSomeWork(object state)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private object SignalCancel(object state)
|
||||
{
|
||||
ManualResetEvent cancelWaitHandle = state as ManualResetEvent;
|
||||
Thread.Sleep(250);
|
||||
cancelWaitHandle.Set();
|
||||
return null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Concurrency()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WaitForIdle()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnIdleEvent()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MultipleGroups()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
using Amib.Threading.Internal;
|
||||
|
||||
using SmartThreadPoolTests;
|
||||
|
||||
namespace PriorityQueueTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestWorkItemsQueue.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestWorkItemsQueue")]
|
||||
public class TestWorkItemsQueue
|
||||
{
|
||||
public TestWorkItemsQueue()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Init()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IdempotenceWaiterEntry()
|
||||
{
|
||||
WorkItemsQueue q = new WorkItemsQueue();
|
||||
|
||||
Assert.AreEqual(0, q.WaitersCount);
|
||||
|
||||
WorkItemsQueue.WaiterEntry we1 = new Amib.Threading.Internal.WorkItemsQueue.WaiterEntry();
|
||||
q.PushWaiter(we1);
|
||||
|
||||
Assert.AreEqual(1, q.WaitersCount);
|
||||
|
||||
q.PushWaiter(we1);
|
||||
|
||||
Assert.AreEqual(1, q.WaitersCount);
|
||||
|
||||
WorkItemsQueue.WaiterEntry we2 = new Amib.Threading.Internal.WorkItemsQueue.WaiterEntry();
|
||||
q.PushWaiter(we2);
|
||||
|
||||
Assert.AreEqual(2, q.WaitersCount);
|
||||
|
||||
q.PushWaiter(we2);
|
||||
|
||||
Assert.AreEqual(2, q.WaitersCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user