SmartThreadPool v1.0
This commit is contained in:
Ami Bar
2009-12-19 16:27:08 +02:00
parent 8d9c132b24
commit b30b4abdda
65 changed files with 11818 additions and 27 deletions
+58
View File
@@ -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("")]
+225
View File
@@ -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;
}
}
}
}
+168
View File
@@ -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>
+97
View File
@@ -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)
{
}
}
}
+87
View File
@@ -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);
}
}
}
+198
View File
@@ -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;
}
}
}
+232
View File
@@ -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;
}
}
}
+227
View File
@@ -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;
}
}
}
+169
View File
@@ -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;
}
}
}
}
}
+121
View File
@@ -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;
}
}
}
+144
View File
@@ -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;
}
}
}
+65
View File
@@ -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;
}
}
}
+101
View File
@@ -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)
{
}
}
}
+99
View File
@@ -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;
}
}
}
+89
View File
@@ -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);
}
}
}
+166
View File
@@ -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;
}
}
}
+227
View File
@@ -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;
}
}
}
+231
View File
@@ -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;
}
}
}
+148
View File
@@ -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;
}
}
}
+109
View File
@@ -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;
}
}
}
+80
View File
@@ -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;
}
}
}
+190
View File
@@ -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()
{
}
}
}
+54
View File
@@ -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);
}
}
}