Click here to Skip to main content
15,884,298 members
Articles / Programming Languages / C#

Some Useful Concurrency Classes and A Small Testbench

Rate me:
Please Sign up or sign in to vote.
4.92/5 (37 votes)
15 Jan 2007CPOL70 min read 102.6K   1K   140  
Useful concurrency classes and small test bench in C#
using System;
using System.Threading;
using System.Collections.Generic;
using NUnit.Framework;

using MPFramework.AppCore.QualityAssurance;
using MPFramework.AppCore.PlatformUtilities;
using MPFramework.AppCore.Manufacturing.SpecializedTypes;

namespace MPFramework.AppCore.MultiProcessing
{
	#region Delegates for Testing Utilities
	/// <summary>
	/// This delegate is used to implement a wrapper for a caller for delegated
	/// Int32 operations. It accepts a delegate that performs a binary operation
	/// on Int32 variables. A source of data and a writable target to be modified
	/// by the operation are also provided as arguments. The delegate is used in
	/// various experiments regarding concurrent access to the writable target.
	/// </summary>
	/// <param name="target">
	/// This is the output target of the operation. It is typically accessed concurrently
	/// by multiple <see cref="System.Threading.Thread"/>s to evaluate concurrency
	/// issues.
	/// </param>
	/// <param name="source">
	/// This is the source of the operation. It is used to somehow modify the target.
	/// An example would be an integer to add to the target.
	/// </param>
	/// <param name="oP">
	/// This is the delegate that performs the integer operation. Again, a simple
	/// example would be an addition operation.
	/// </param>
	/// <param name="lastValue">
	/// This is the original value that was contained in the target if there were
	/// no collisions. If there were collisions (another Thread snuck in and modified
	/// the value <see paramref="target"/> during the operation) the last updated 
	/// value is returned.
	/// </param>
	/// <returns>
	/// The return value indicates whether or not another Thread modified the target
	/// during the operation. In this case, the method will use the most recently
	/// loaded target value, which will usually be different than the target's value
	/// before this method is called.
	/// </returns>
	/// <remarks>
	/// This delegate is used to evaluate the performance of "retry loops", among
	/// other concurrency management techniques. One version of a retry loop utilizes
	/// the <see cref="System.Threading.Interlocked.CompareExchange(ref int, int, int)"/>
	/// method. The <see paramref="target"/>, <see paramref="source"/> and <see paramref="lastValue"/>
	/// parameters are employed to support concurrency experiments that utilize this
	/// method.
	/// </remarks>
	public delegate System.Boolean Int32ConcurrentOpCaller(ref System.Int32 target,
		System.Int32 source, Int32Op oP, out System.Int32 lastValue);
	/// <summary>
	/// This delegate is designed to perform the same function, this time on our
	/// wrapped value Type, (an "RVT"), which must implement
	/// <see cref="IReferencedValueType&lt;UValueType&gt;"/>. In this case, the
	/// delegate outputs a ValueType in the "out" parameter, which is the old value
	/// that was wrapped by the target. Also note that the target is no longer 
	/// passed with the "ref" keyword, since it is a class (passed by reference
	/// already) and we perform operations on Types wrapped inside the class.
	/// </summary>
	public delegate System.Boolean RVTTypeConcurrentOpCaller<T,UValueType>(
		T target, T source,	RVTOp<T,UValueType> rVToP, out UValueType lastValue)
			where T : class, IReferencedValueType<UValueType> where UValueType : struct;
	/// <summary>
	/// This one handles an RVT just by it's interface. It's generally preferable
	/// to handle a Type through an interface when access to the full Type is 
	/// not required. Note that source and target arguments, being Interfaces
	/// are again passed by reference, so there is no need for the "ref" keyword.
	/// </summary>
	public delegate System.Boolean IRVTConcurrentOpCaller<UValueType>(
		IReferencedValueType<UValueType> target, IReferencedValueType<UValueType> source,
			IRVTOp<UValueType> rVToP, out UValueType lastValue)
				where UValueType : struct;
	#endregion // Delegates for Testing Utilities
	#region Static Test Data Class
	/// <summary>
	/// Container for common test data. These data may be specific to MSWindows.
	/// The data may need to be changed for other platforms and languages. We
	/// refer to this class as the "static data store".
	/// </summary>
	[PlatformSpecific(PlatformsSupported = CLRPlatformsSupported.MSWNT)]
	public static class QATester_MultiProcessing_Testdata
	{
		#region Static Fields
		// These are the "standard" settings. Create your own versions for custom
		// tests.
		/// <summary>
		/// The number of Threads we allocate for our tests. This default is used
		/// for extreme stress testing. 500 CLR Threads do work nicely most of the
		/// time on a capable XP machine. For most tests we set it to 5 or 10 or so.....
		/// </summary>
		internal static readonly int s_numThreadsAllocated = 500;
		/// <summary>
		/// The number of Threads we allocate for our tests.
		/// </summary>
		internal static readonly int s_defaultNumThreadsInUse = s_numThreadsAllocated;
		/// <summary>
		/// The number of Threads in use for a particular test.
		/// </summary>
		internal static int s_numThreadsInUse = s_defaultNumThreadsInUse;
		#region Int32 Stuff
		///////////////////////////////////////////////////////////////////////
		// This region contains static data for Int32 tests. More complex tests
		// allocate data in local test classes.
		///////////////////////////////////////////////////////////////////////
		/// <summary>
		/// A set of Threads for the tests.
		/// </summary>
		internal static readonly Int32ThreadData[] s_testInt32ThreadData = null;
		/// <summary>
		/// This variable is loaded with the Main Thread's information in a
		/// given test if we are interested in examining it after the test.
		/// </summary>
		internal static readonly Int32ThreadData s_mainInt32ThreadData = null;
		/// <summary>
		/// Random number generator for Thread start/stop and various simulated
		/// processing delays. This is the static one that is not Thread-dependent.
		/// We spawn generators off this one for each Thread.
		/// </summary>
		internal static readonly IAuditingGenerator<Int32> s_Int32RngDelays;
		/// <summary>
		/// Random number generator for generation of random Int's. This is the static
		/// one that is not Thread-dependent. We spawn generators off this one for
		/// each Thread.
		/// </summary>
		internal static readonly IAuditingGenerator<Int32> s_Int32RngNumbers;
		/// <summary>
		/// A target for testing Thread collisions. This one's not readonly, since we
		/// use it for I/O.
		/// </summary>
		public static Int32 s_multiaccessInt32Target = 0;
		/// <summary>
		/// The default initial value for the target.
		/// </summary>
		public static Int32 s_defaultMultiaccessInt32TargetInitialValue = 0;
		/// <summary>
		/// Reporting on/off.
		/// </summary>
		public static Boolean s_reportToScreen = true;
		#endregion // Int32 Stuff
		#endregion // Static Fields
		#region Static Constructor
		/// <summary>
		/// Constructor sets up the default RNG's and does the allocation for
		/// the "standard" Int32 Worker Thread data.
		/// </summary>
		static QATester_MultiProcessing_Testdata()
		{
			// This is the default copy of the delay generator. It's set up to
			// cause some collisions in the CE-based retry loop. Seed 0, Delays
			// range from 1 to 1000 - no special OP needed (null), OP state
			// initialized from target, no logging (false).
			s_Int32RngDelays
				= new AuditingInt32RNGenerator(
					0, 1, 1000, null, s_multiaccessInt32Target, false);
			// This is the default Int32 data generator. Seed 1025, Numbers range
			// from -100 to 100 - no special op needed, OP state initialized from
			// target, no logging.
			s_Int32RngNumbers
				= new AuditingInt32RNGenerator(
					1025, -100, 100, null, s_multiaccessInt32Target, false);
			// Allocate the data for the Threads.
			s_testInt32ThreadData = new Int32ThreadData[s_numThreadsAllocated];
			// Set 'em up.
			for(int i = 0; i < s_numThreadsAllocated; i++)
				s_testInt32ThreadData[i] = new Int32ThreadData();
			// Don't forget the Main Thread...
			s_mainInt32ThreadData = new Int32ThreadData();
		}
		#endregion // Static Constructor
		#region Static Class Methods
		#region Utility Methods
		///////////////////////////////////////////////////////////////////////
		//// This region contains a few methods to manipulate the test class'
		//// basic data for test setup.
		///////////////////////////////////////////////////////////////////////
		/// <summary>
		/// This one aborts all Threads and waits until they are gone, then
		/// clears out the CallerObjects by setting to <c>null</c>. Then it
		/// clears out the Main Thread's ThreadData so a Main Thread is no
		/// longer under test. Note that this method only works on the default
		/// Threads provided within <see cref=" QATester_MultiProcessing_Testdata"/>.
		/// If you build your own Threads or data locally, you have to clean them
		/// up.
		/// </summary>
		internal static void ClearThreads()
		{
			// Kill all the Threads and monitor their death.
			foreach(Int32ThreadData tD in s_testInt32ThreadData) {
				while((tD.m_thread != null) && (tD.m_thread.IsAlive)) {
					tD.m_thread.Abort();
				}
			}
			// Unregister them.
			foreach(Int32ThreadData tD in s_testInt32ThreadData) {
				tD.m_callerObject = null;
				tD.m_thread = null;
			}
			// Unregister the Main Thread.
			s_mainInt32ThreadData.m_callerObject = null;
			s_mainInt32ThreadData.m_thread = null;
		}
		/// <summary>
		/// This one digs out the Thread data corresponding to the Id. Again, only
		/// works on <see cref=" QATester_MultiProcessing_Testdata"/>.
		/// </summary>
		internal static Int32ThreadData GetThreadData(int managedThreadId)
		{
			foreach(Int32ThreadData tD in s_testInt32ThreadData)
				if((tD.m_thread != null) && (tD.m_thread.ManagedThreadId == managedThreadId)) return tD;
			// If it's not a spawned Thread, it must be the current.
			return QATester_MultiProcessing_Testdata.s_mainInt32ThreadData;
		}
		/// <summary>
		/// This method resets the test data to their initial default values.
		/// </summary>
		/// <remarks>
		/// In any test, this method can be called to reset the static data to its
		/// default values, then the data can be "recustomized" by the test designer.
		/// </remarks>
		internal static void ResetData()
		{
			// Just copy stuff over.
			s_numThreadsInUse = s_defaultNumThreadsInUse;
			s_multiaccessInt32Target = s_defaultMultiaccessInt32TargetInitialValue;
		}
		#endregion // Utility Methods
		#region Static Test Methods
		#region TestRunners (Process Controllers)
		///////////////////////////////////////////////////////////////////////
		// This region contains a number of testrunner "Shells" that are
		// designed to set up and monitor the operation of multiple Threads
		// which are operating concurrently. We use these TestRunners in our
		// testing procedures to evaluate various concurrency issues. They also
		// provide an elementary starting point for the development of more
		// sophisticated controllers that might be used in practical
		// applications.
		///////////////////////////////////////////////////////////////////////
		/// <summary>
		/// This method is a testrunner shell for use in QA testing of multithreaded
		/// constructs. It uses <see cref="QATester_MultiProcessing_Testdata.PIInt32CallerProcess"/>
		/// as a delegate process to be passed to a Thread constructor as the
		/// <see cref="ParameterizedThreadStart"/> argument. This delegate takes a
		/// <see cref="System.Object"/> argument at Thread start time which is either
		/// populated by the user and passed in or taken from preset static data.
		/// This TestRunner attempts to give a simple demonstration of how to start
		/// and monitor a number of Threads without using any Generics.
		/// </summary>
		/// <param name="int32CallerObject">
		/// This is a CallerObject that contains data for the various Threads, including
		/// the Main Thread, if <see paramref="processOnMain"/> is <c>true</c>. This
		/// parameter will be accessed if the CallerObjects have not been set in the
		/// ThreadData array for the spawned Threads (if any), or if the CallerObject
		/// has not been set for the Main Thread (if <see paramref="processOnMain"/>
		/// is <c>true</c>). If this CallerObject is accessed, it is copied to the
		/// Main Thread and Worker Thread CallerObjects (as needed) and the new objects
		/// have their generators initialized with a new state that is derived from the
		/// Thread ID. If all Threads that are to be used in a given test have their
		/// CallerObject preloaded, this argument may be passed as <c>null</c>.
		/// </param>
		/// <param name="processOnMain">
		/// If <c>true</c>, this parameter signals that a copy of the processing
		/// delegate should be fired up on the Main Thread. This copy of the
		/// delegate is called after all the Worker Threads have been started. The
		/// Worker Threads are joined by the Main Thread after the Main Thread
		/// returns from its processing.
		/// </param>
		/// <remarks>
		/// <para>
		/// Different operations with different random characteristics can be associated
		/// with different Threads (both Worker Threads and Main Thread) by presetting
		/// the CallerObjects for each of these in the static data store.
		/// </para>
		/// <para>
		/// This TestRunner utilizes a fixed CallerProcess delegate,
		/// <see cref="QATester_MultiProcessing_Testdata.PIInt32CallerProcess"/>.
		/// </para>
		/// </remarks>
		public static void Int32TestRunner(Int32ConcurrentOpCallerObject int32CallerObject,
			bool processOnMain)
		{
			// This is the "standard" caller delegate we use in this method.
			ParameterizedThreadStart Int32CallerProcessDelegate
				= QATester_MultiProcessing_Testdata.PIInt32CallerProcess;
			// Unregister Main Thread.
			QATester_MultiProcessing_Testdata.s_mainInt32ThreadData.m_thread = null;
			// If the user has decided to also process on the Main Thread, initialize it.
			if(processOnMain)
				QATester_MultiProcessing_Testdata.s_mainInt32ThreadData.m_thread = Thread.CurrentThread;
			// In this loop, we create each Thread and spawn a new CallerObject for it
			// if it has not been preloaded by the user.
			Thread newThread;
			for(int i = 0; i < QATester_MultiProcessing_Testdata.s_numThreadsInUse; i++) {
				newThread = new Thread(new ParameterizedThreadStart(Int32CallerProcessDelegate));
				newThread.Name = String.Format("Worker Thread #{0}", i + 1);
				QATester_MultiProcessing_Testdata.s_testInt32ThreadData[i].m_thread = newThread;
				// If any given CallerObject is not preset, spawn a new one from the default.
				if(QATester_MultiProcessing_Testdata.s_testInt32ThreadData[i].m_callerObject == null) {
					QATester_MultiProcessing_Testdata.s_testInt32ThreadData[i].m_callerObject
						= int32CallerObject.SpawnCallerObject(newThread.ManagedThreadId);
				}
			}
			// If Main Thread has been loaded, we must set it up.
			Int32ThreadData mainThreadData = QATester_MultiProcessing_Testdata.s_mainInt32ThreadData;
			if(mainThreadData.m_thread != null) {
				// Ensure it has data.
				if(mainThreadData.m_callerObject == null) {
					mainThreadData.m_callerObject
						= int32CallerObject.SpawnCallerObject(mainThreadData.m_thread.ManagedThreadId);
				}
				// Give it a name if it doesn't have one.
				if(String.IsNullOrEmpty(mainThreadData.m_thread.Name))
					mainThreadData.m_thread.Name = String.Format("Main");
			}
			// In this loop, we fire the Threads up.
			for(int i = 0; i < QATester_MultiProcessing_Testdata.s_numThreadsInUse; i++) {
				Thread thread = QATester_MultiProcessing_Testdata.s_testInt32ThreadData[i].m_thread;
				Console.WriteLine("Starting Thread: \"{0}\",  ManagedThreadID #: {1}",
						thread.Name, thread.ManagedThreadId);
				thread.Start(QATester_MultiProcessing_Testdata.s_testInt32ThreadData[i].m_callerObject);
			}
			// If Main Thread should work, let it.
			if(mainThreadData.m_thread != null) {
				Console.WriteLine("Starting Thread: \"{0}\",  ManagedThreadID #: {1}",
						mainThreadData.m_thread.Name, mainThreadData.m_thread.ManagedThreadId);
				Int32CallerProcessDelegate(mainThreadData.m_callerObject);
			}
			// Wait for all the Threads to finish.
			for(int i = 0; i < QATester_MultiProcessing_Testdata.s_numThreadsInUse; i++) {
				QATester_MultiProcessing_Testdata.s_testInt32ThreadData[i].m_thread.Join();
			}
		}
		/// <summary>
		/// This is a test runner for a Generic RVT. This runner utilizes the caller
		/// that is parameterized by a Generic class wrapping a Generic ValueType.
		/// </summary>
		/// <typeparam name="T">
		/// This is the class that is wrapping the Generic struct that we want to
		/// manipulate.
		/// </typeparam>
		/// <typeparam name="UValueType">
		/// This is the Generic struct.
		/// </typeparam>
		/// <param name="rVTCallerObject">
		/// A <see cref="RVTTypeConcurrentOpCallerObject&lt;T, UValueType&gt;"/> that
		/// carries default Thread data.
		/// </param>
		/// <param name="threadDataArray">
		/// This may be <c>null</c>. If so, it will be created and populated with
		/// copies of the random # generator on the incoming <see paramref="rVTCallerObject"/>
		/// which have been initialized with the Thread Id's of the Threads in use. If
		/// it is not <c>null</c>, it must be of the correct dimension to handle
		/// all Threads, including the Main, if it is in use. It is not necessary to
		/// load any element of the array with a CallerObject. Any CallerObject not
		/// present will be created internally by spawning a CallerObject as described
		/// in <see cref="QATester_MultiProcessing_Testdata.Int32TestRunner"/> above.
		/// The array must be dimensioned correctly if it is not <c>null</c>, however.
		/// </param>
		/// <param name="numSpawnedThreads">
		/// This is the number of Worker Threads that are spawned by the Main Thread.
		/// The total number of active Threads will be numSpawnwdThreads + 1 if
		/// <see paramref="processOnMain"/> is <c>true</c>.
		/// </param>
		/// <param name="processOnMain">
		/// If <c>true</c>, this parameter signals that a copy of the processing
		/// delegate should be fired up on the Main Thread. This copy of the
		/// delegate is called after all the Worker Threads have been started. The
		/// Worker Threads are joined by the Main Thread after the Main Thread
		/// returns from its processing.
		/// </param>
		/// <Exceptions>
		/// <Exception>
		/// An <see cref="ApplicationException"/> is generated with the message
		/// "Bad size on threadDataArray" if the <see paramref="threadDataArray"/>
		/// is not <c>null</c> but not not of adequate size.
		/// </Exception>
		/// </Exceptions>
		/// <remarks>
		/// <para>
		/// This method generalizes things by allowing an arbitrary Generic Type (within
		/// our constraints) to be operated upon and also allows Thread data to be passed
		/// in as an argument for individual Threads. The number of Worker Threads that
		/// are created (spawned) by the TestRunner is also passed as a parameter. These
		/// data are no longer taken from the static store as in
		/// <see cref="QATester_MultiProcessing_Testdata.Int32TestRunner"/>.
		/// </para>
		/// <para>
		/// This TestRunner utilizes a fixed CallerProcess delegate,
		/// <see cref="QATester_MultiProcessing_Testdata.RVTConcurrentCallerProcess&lt;T, UValueType&gt;"/>.
		/// </para>
		/// </remarks>
		public static void RVTTypeTestRunner<T, UValueType>(
			RVTTypeConcurrentOpCallerObject<T, UValueType> rVTCallerObject,
				RVTTypeThreadData<T, UValueType>[] threadDataArray, Int32 numSpawnedThreads,
				bool processOnMain)
			where T : class, IReferencedValueType<UValueType>, new()
			where UValueType : struct
		{
			// This is the "standard" caller delegate we use in this method.
			ParameterizedThreadStart rVTCallerDelegate
				= QATester_MultiProcessing_Testdata.RVTConcurrentCallerProcess<T, UValueType>;
			// Total number of Threads, including Main.
			Int32 totalNumThreads = numSpawnedThreads;
			// Gotta' bump it up if Main is processing.
			if(processOnMain) totalNumThreads++;
			// We allow null - we just do everything internally....
			if(threadDataArray == null) {
				// Build a new ThreadData array.
				threadDataArray = new RVTTypeThreadData<T, UValueType>[totalNumThreads];
				for(Int32 i = 0; i < totalNumThreads; i++)
					threadDataArray[i] = new RVTTypeThreadData<T, UValueType>();
			}
			else {
				// Well, we might as well do some checking.
				if(threadDataArray.Length < totalNumThreads)
					throw new ApplicationException("Bad size on threadDataArray");
			}
			// If the user has decided to also process on the Main Thread, initialize it.
			if(processOnMain)
				threadDataArray[numSpawnedThreads].m_thread = Thread.CurrentThread;
			// In this loop, we create each Thread and spawn a new CallerObject for it
			// if it has not been preloaded by the user.
			Thread newThread;
			for(int i = 0; i < numSpawnedThreads; i++) {
				newThread = new Thread(new ParameterizedThreadStart(rVTCallerDelegate));
				newThread.Name = String.Format("Worker Thread #{0}", i + 1);
				threadDataArray[i].m_thread = newThread;
				// If any given CallerObject is not preset, spawn a new one from the default.
				if(threadDataArray[i].m_callerObject == null) {
					threadDataArray[i].m_callerObject
						= rVTCallerObject.SpawnCallerObject(newThread.ManagedThreadId);
				}
			}
			// If Main Thread has been loaded, we must set it up.
			if(processOnMain) {
				// Ensure it has data.
				if(threadDataArray[numSpawnedThreads].m_callerObject == null) {
					threadDataArray[numSpawnedThreads].m_callerObject
						= rVTCallerObject.SpawnCallerObject(threadDataArray[numSpawnedThreads].m_thread.ManagedThreadId);
				}
				// Give it a name if it doesn't have one.
				if(String.IsNullOrEmpty(threadDataArray[numSpawnedThreads].m_thread.Name))
					threadDataArray[numSpawnedThreads].m_thread.Name = String.Format("Main");
			}
			// In this loop, we fire the Threads up.
			for(int i = 0; i < numSpawnedThreads; i++) {
				Thread thread = threadDataArray[i].m_thread;
				Console.WriteLine("Starting Thread: \"{0}\",  ManagedThreadID #: {1}",
					thread.Name, thread.ManagedThreadId);
				thread.Start(threadDataArray[i].m_callerObject);
			}
			// If Main Thread should work, let it.
			if(processOnMain) {
				Console.WriteLine("Starting Thread: \"{0}\",  ManagedThreadID #: {1}",
					threadDataArray[numSpawnedThreads].m_thread.Name,
						threadDataArray[numSpawnedThreads].m_thread.ManagedThreadId);
				rVTCallerDelegate(threadDataArray[numSpawnedThreads].m_callerObject);
			}
			// Wait for all the Threads to finish.
			for(int i = 0; i < numSpawnedThreads; i++) {
				threadDataArray[i].m_thread.Join();
			}
		}
		/// <summary>
		/// This is a test runner for a Generic IRVT. Substantially the same as
		/// <see cref="RVTTypeTestRunner&lt;T, UValueType&gt;"/>, except we deal
		/// with the IRVT's, not the full Generic classes. We pass the CallerProcess
		/// method to this method through it's delegate. We also add one more
		/// feature. We read the <c>NumCallsOnThread</c> property on the Main Thread's
		/// data, if <see paramref="processOnMain"/> is <c>true</c>. If this is set
		/// to -1, we demonstrate how to gracefully terminate the Worker Thread's
		/// processing by changing a data item that the Worker Threads have access to.
		/// </summary>
		/// <typeparam name="UValueType">
		/// This is the Generic struct.
		/// </typeparam>
		/// <param name="iRVTCallerProcessDelegate">
		/// This is the delegate that performs processing on Threads. This single
		/// delegate is common across all Threads.
		/// </param>
		/// <param name="iRVTCallerObject">
		/// A <see cref="IRVTConcurrentOpCallerObject&lt;T&gt;"/> that carries
		/// default Thread data.
		/// </param>
		/// <param name="threadDataArray">
		/// This may be <c>null</c>. If so, it will be created and populated with
		/// copies of the random # generator on the incoming <see paramref="iRVTCallerObject"/>
		/// which have been initialized with the Thread Id's of the Threads in use. If
		/// it is not <c>null</c>, it must be of the correct dimension to handle
		/// all Threads, including the Main, if it is in use. It is not necessary to
		/// load any elment of the array with a CallerObject. Any CallerObject not
		/// present will be created internally by spawning a CallerObject as described
		/// in <see cref="QATester_MultiProcessing_Testdata.Int32TestRunner"/> above.
		/// The array must be dimensioned correctly if it is not <c>null</c>, however.
		/// </param>
		/// <param name="numSpawnedThreads">
		/// This is the number of Worker Threads that are spawned by the Main Thread.
		/// The total number of active Threads will be numSpawnwdThreads + 1 if
		/// <see paramref="processOnMain"/> is <c>true</c>.
		/// </param>
		/// <param name="processOnMain">
		/// If <c>true</c>, this parameter signals that a copy of the processing
		/// delegate should be fired up on the Main Thread. This copy of the
		/// delegate is called after all the Worker Threads have been started. The
		/// Worker Threads are joined by the Main Thread after the Main Thread
		/// returns from its processing.
		/// </param>
		/// <Exceptions>
		/// <Exception>
		/// An <see cref="ApplicationException"/> is generated with the message
		/// "Bad size on threadDataArray" if the <see paramref="threadDataArray"/>
		/// is not <c>null</c> but not not of adequate size.
		/// </Exception>
		/// </Exceptions>
		/// <remarks>
		/// <para>
		/// <see paramref="processOnMain"/> must be enabled (<c>true</c>) for the
		/// Main Thread to employ the internal StatusRegister and ControlRegister
		/// to demonstrate the control of Worker Threads.
		/// </para>
		/// <para>
		/// Note that, although we do not attempt it within these classes, it is
		/// perfectly feasible to pass an array of <see cref="ParameterizedThreadStart"/>
		/// objects to allow different Threads to be running different processes.
		/// </para>
		/// </remarks>
		public static void IRVTTestRunner<UValueType>(
			ParameterizedThreadStart iRVTCallerProcessDelegate,
				IRVTConcurrentOpCallerObject<UValueType> iRVTCallerObject,
					IRVTThreadData<UValueType>[] threadDataArray, Int32 numSpawnedThreads,
						bool processOnMain)
			where UValueType : struct
		{
			// Total number of Threads, including Main.
			Int32 totalNumThreads = numSpawnedThreads;
			// Gotta' bump it up if Main is processing.
			if(processOnMain) totalNumThreads++;
			// We allow null - we just do everything internally....
			if(threadDataArray == null) {
				// Build a new ThreadData array.
				threadDataArray = new IRVTThreadData<UValueType>[totalNumThreads];
				for(Int32 i = 0; i < totalNumThreads; i++)
					threadDataArray[i] = new IRVTThreadData<UValueType>();
			}
			else {
				// Well, we might as well do some checking.
				if(threadDataArray.Length < totalNumThreads)
					throw new ApplicationException("Bad size on threadDataArray");
			}
			// If the user has decided to also process on the Main Thread, initialize
			// it.
			if(processOnMain)
				threadDataArray[numSpawnedThreads].m_thread = Thread.CurrentThread;
			// In this loop, we create each Thread and spawn a new CallerObject for it
			// if it has not been preloaded by the user.
			Thread newThread;
			for(int i = 0; i < numSpawnedThreads; i++) {
				newThread = new Thread(new ParameterizedThreadStart(iRVTCallerProcessDelegate));
				newThread.Name = String.Format("Worker Thread #{0}", i + 1);
				threadDataArray[i].m_thread = newThread;
				// If a particular CallerObject is not preset, spawn a new one from the default.
				if(threadDataArray[i].m_callerObject == null) {
					threadDataArray[i].m_callerObject
						= iRVTCallerObject.SpawnCallerObject(newThread.ManagedThreadId);
				}
			}
			// If Main Thread has been loaded, we must set it up.
			if(processOnMain) {
				// Ensure it has data.
				if(threadDataArray[numSpawnedThreads].m_callerObject == null) {
					threadDataArray[numSpawnedThreads].m_callerObject
						= iRVTCallerObject.SpawnCallerObject(threadDataArray[numSpawnedThreads].m_thread.ManagedThreadId);
				}
				// Give it a name if it doesn't have one.
				if(String.IsNullOrEmpty(threadDataArray[numSpawnedThreads].m_thread.Name))
					threadDataArray[numSpawnedThreads].m_thread.Name = String.Format("Main");
			}
			// In this loop, we fire the Threads up.
			for(int i = 0; i < numSpawnedThreads; i++) {
				Thread thread = threadDataArray[i].m_thread;
				Console.WriteLine("Starting Thread: \"{0}\",  ManagedThreadID #: {1}",
						thread.Name, thread.ManagedThreadId);
				thread.Start(threadDataArray[i].m_callerObject);
			}
			// If Main Thread should work, let it.
			if(processOnMain) {
				Console.WriteLine("Starting Thread: \"{0}\",  ManagedThreadID #: {1}",
					threadDataArray[numSpawnedThreads].m_thread.Name,
						threadDataArray[numSpawnedThreads].m_thread.ManagedThreadId);
				iRVTCallerProcessDelegate(threadDataArray[numSpawnedThreads].m_callerObject);
				// The Main Thread uses the "ControlRegister" on it's Thread object to
				// indicate that Worker Threads should somehow be controlled. In this
				// example test runner, we just set it to a positive. IRVTConcurrentCaller
				// is set up to interpret this as a stop command.
				//
				// We, ourselves, use a -1 to indicate that we are in "control" mode,
				// otherwise our own Thread process would get shut down early.
				if(threadDataArray[numSpawnedThreads].m_callerObject.m_controlRegister == -1){
					// We put in a completely arbitrary test here that waits until
					// every Thread has done at least 3 iterations before shutting
					// them all down. This is a simple example of how Worker Threads
					// can communicate their status back to a controller through a
					// data item. This is an inefficient waiting loop (no timers,
					// no waits, etc.) that just monitors the StatusRegisters associated
					// with each Worker Thread.
					bool stopThreads = false;
					while(!stopThreads) {
						// Assume we will stop.
						stopThreads = true;
						for(int i = 0; i < numSpawnedThreads; i++) {
							if(threadDataArray[i].m_callerObject.m_statusRegister < 3)
								// If somebody isn't finished, we can't stop yet.
								stopThreads = false;
						}
					}
					// Tell all the Threads to stop at the end of the current
					// loop iteration.
					for(int i = 0; i < numSpawnedThreads; i++) {
						threadDataArray[i].m_callerObject.m_controlRegister = 1;
						Thread thread = threadDataArray[i].m_thread;
						Console.WriteLine("Stopping Thread: \"{0}\" ,  ManagedThreadID #: {1}",
							thread.Name, thread.ManagedThreadId);
					}
				}
			}
			// Wait for all the Threads to finish.
			for(int i = 0; i < numSpawnedThreads; i++) {
				threadDataArray[i].m_thread.Join();
			}
		}
		#endregion //TestRunners (Process Controllers)
		#region Worker Thread Processes
		///////////////////////////////////////////////////////////////////////
		// This section contain testing processes that call operations on Threads
		// with random delays and random data to simulate actual operation of
		// Threads accessing data concurrently. These processes are designed to
		// be used as ParameterizedThreadStart delegates that are available
		// under .Net 2.0. The processes accept an Object that contains per-Thread
		// data to be passed to Threads.
		///////////////////////////////////////////////////////////////////////
		/// <summary>
		/// This is a procedure that runs on each Thread and accesses shared
		/// data. It is specialized to use only Int32 data - it is designed to
		/// call a CallerObject's Int32 generator and use it to provide a source
		/// of Int32 numbers for testing multithreaded access to an Int32 variable.
		/// It is designed to be passed to the parameterized <see cref="ThreadStart"/>
		/// constructor.
		/// </summary>
		/// <param name="threadObject">
		/// This object must be a <see cref="Int32ConcurrentOpCallerObject"/>.
		/// </param>
		public static void PIInt32CallerProcess(System.Object threadObject)
		{
			// A bool needed to report a collision.
			bool collision = false;
			// To catch the last value.
			Int32 lastValue;
			Int32ConcurrentOpCallerObject callerObject
				= (Int32ConcurrentOpCallerObject)threadObject;
			// Two for handling our currently executing Thread.
			Int32 iD = Thread.CurrentThread.ManagedThreadId;
			string threadName = Thread.CurrentThread.Name;
			// Fetch the generator from the Thread data. AuditingInt32RNGenerator
			// is handled on the CallerObject as an IAuditingGenererator<Int32>.
			// We want to handle it here as a AuditingInt32RNGenerator to demonstrate
			// how the same generator can be handled as a concrete closure defined
			// with a derived Type. This technique would be useful if we wanted to
			// ensure that a specialized generator, optimized for Int32's is used
			// in a critical application. The cast will fail at run-time, of course,
			// if the generator instatntiated on the CallerObject was not an
			// AuditingInt32RNGenerator. However, we happen to know that it is
			// constructed in the static data store as "new AuditingInt32RNGenerator(....)".
			// Note that it would have been possible to define the generator on
			// CallerObject as AuditingInt32RNGenerator if we wanted to ensure
			// compile-time Type safety in a specialized application using only
			// Int32's.
			AuditingInt32RNGenerator generator
				= (AuditingInt32RNGenerator) GetThreadData(iD).m_callerObject.NumberGenerator;
			// Perform the number of calls requested, using the generator.
			for(int i = 0; i < callerObject.NumCallsOnThread; i++) {
				// Issue the call.
				collision
					= callerObject.Caller(ref QATester_MultiProcessing_Testdata.s_multiaccessInt32Target,
						generator.Next(), callerObject.Op, out lastValue);
				// We just indicate a collision on the console.
				if(collision)
					Console.WriteLine("Collision with Thread: \"{0}\"", threadName);
			}
		}
		/// <summary>
		/// This is a Generic method that runs on each Thread and accesses shared
		/// data. It is designed to call a CallerObject's Int32 generator and use it to
		/// provide a source of Type T numbers for testing multithreaded access to
		/// a Type T variable. It is designed to be passed to the parameterized
		/// <see cref="ThreadStart"/> constructor.
		/// </summary>
		/// <param name="threadObject">
		/// This object must be a <see cref="RVTTypeConcurrentOpCallerObject&lt;T, UValueType&gt;"/>.
		/// </param>
		/// <remarks>
		/// <para>
		/// This process delegate allows us to perform concurrency tests on any
		/// object implementing <see cref="IReferencedValueType&lt;UValueType&gt;"/>.
		/// This may be a simple default <see cref="ReferencedValueType&lt;UValueType&gt;"/>,
		/// or a complicated Type implementing the interface, perhaps containing a
		/// simpler <see cref="IReferencedValueType&lt;UValueType&gt;"/> to implement
		/// a lock object.
		/// </para>
		/// <para>
		/// This method imposed an additional constraint on <see typeparamref="T"/>,
		/// namely the "new()" constraint. Because we must construct a local working
		/// copy of <see typeparamref="T"/>, we must know at language compile time
		/// that it is possible to instantiate a default copy. The "new()" constraint
		/// requires that <see typeparamref="T"/> have a "default" or parameterless
		/// constructor.
		/// </para>
		/// </remarks>
		public static void RVTConcurrentCallerProcess<T, UValueType>(System.Object threadObject)
			where T : class, IReferencedValueType<UValueType>, new()
			where UValueType : struct
		{
			// A bool needed to report a collision.
			bool collision = false;
			// This cast will generate an exception if we don't have the correct
			// type of Thread object coming in.
			RVTTypeConcurrentOpCallerObject<T, UValueType> callerObject
				= (RVTTypeConcurrentOpCallerObject<T, UValueType>)threadObject;
			// For reporting on our currently executing Thread.
			string threadName = Thread.CurrentThread.Name;
			// Fetch the generator from the Thread data.
			IAuditingGenerator<Int32> generator
				= callerObject.NumberGenerator;
			// We need to create a copy of the Type from its default constructor.
			// This will fail at runtime if the Type T does not have a default
			// constructor. Thus the new() constraint in the method definition.
			// Here, we really just wanted to demonstrate to folks how to use
			// Activator for a Generic. Note that at runtime the Activator will
			// attempt to create a default version of whatever the loader/JIT
			// resolves for T at loadtime.
			T randomRVT = Activator.CreateInstance<T>();
			// This works, too, because the method has the new() constraint.
			// The difference is that Activator does not need the new() constraint.
			// It would fail at runtime, however, when the reflection subsystem
			// tried to locate a parameterless constructor, if T did not implement
			// one. Note that
			// "MPFramework.AppCore.Manufacturing.SpecializedTypes.ReferencedValueType<T>"
			// implements a default public parameterized constructor. If the method
			// did not specify the "new()" constraint, the following line would receive
			// an error at language compile time.
			randomRVT = new T(); // Wouldn't compile without default constructor on T.
			// Need a UValueType to receive a converted copy of the rn. Note that
			// UValueType is constrained to be a struct, so we get a copy of UValueType's
			// databytes in a HOME in local storage. Note that we could not have
			// created T this way. T, being constrained to be a C# class
			// (a non-ValueType .Net Class) would result in a null reference being
			// returned from default(T).
			UValueType uValueType = default(UValueType);
			// One for the "out" variable, too.
			UValueType outUValueType = default(UValueType);
			// Perform the number of calls requested, using the generator.
			for(int i = 0; i < callerObject.NumCallsOnThread; i++) {
				// Generate the rn and leave it in the generator.
				generator.Next();
				// Convert it using our catch-all ConvertNumber method.
				// Note this line will not compile, since we have defined the
				// generator as an IAuditingGenerator<Int32>.
				// uValueType = generator.Next();  !!!!!!  This won't compile.
				//
				// Let the generator convert the rn. It figures out whether it
				// can convert to us or not. Generator will throw the exception
				// - this cast will always succeed if the generator returns something.
				//
				// Of course, if this were a real program, we'd catch or document
				// the exception..........
				uValueType = (UValueType)generator.ConvertNumber(typeof(UValueType));
				// Now wrap it in the RVT.
				randomRVT.Value = uValueType;
				// Issue the call.
				collision = callerObject.Caller(callerObject.m_target,
					randomRVT, callerObject.Op, out outUValueType);
				// Just indicate a collision on the console.
				if(collision)
					Console.WriteLine("Collision with Thread: \"{0}\"", threadName);
			}
		}
		/// <summary>
		/// This is the Thread process for IRVT's. It is almost the same as the
		/// previous one, except it handles an RVT through its interface, which
		/// gives us more flexibility in adding IRVT functionality to a general
		/// object. It also demonstrates the ability to control a "well-behaved"
		/// Thread by setting a data item that the executing Thread can read.
		/// </summary>
		/// <param name="threadObject">
		/// This object must be a <see cref="IRVTConcurrentOpCallerObject&lt;UValueType&gt;"/>.
		/// </param>
		/// <remarks>
		/// This process delegate allows us to perform concurrency tests on any
		/// object implementing <see cref="IReferencedValueType&lt;UValueType&gt;"/>.
		/// This may be a simple default <see cref="ReferencedValueType&lt;UValueType&gt;"/>,
		/// or a complicated Type implementing the interface, perhaps containing a
		/// simpler <see cref="IReferencedValueType&lt;UValueType&gt;"/> to implement
		/// a lock object.
		/// </remarks>
		public static void IRVTConcurrentCallerProcess<UValueType>(System.Object threadObject)
			where UValueType : struct
		{
			// A bool needed to report a collision.
			bool collision = false;
			// This cast will generate an exception if we don't have the correct
			// type of Thread object coming in.
			IRVTConcurrentOpCallerObject<UValueType> callerObject
				= (IRVTConcurrentOpCallerObject<UValueType>)threadObject;
			// For reporting on our currently executing Thread.
			string threadName = Thread.CurrentThread.Name;
			// Fetch the generator from the Thread data. In this case, the generator
			// is instantiated as an Int32 generator. We do this to show the possibility
			// of using the "back door" in our generator, the ConvertNumber function,
			// to employ an Int32 generator to produce an arbitrary Type at run
			// time (anything we've designed it internally to convert, anyway).
			IAuditingGenerator<UValueType> generator
				= callerObject.NumberGenerator;
			// We need something wearing IReferencedValueType<UValueType> to wrap
			// rn's. -  a default ReferencedValueType<UValueType> is fine. Note
			// that this does not require any "new()" constraint on the method,
			// since we are constructing a specific closed Type (closed on T) that
			// is known at language compile time.
			IReferencedValueType<UValueType> randomRVT
				= new ReferencedValueType<UValueType>();
			// Need a UValueType to receive a converted copy of the rn.
			UValueType uValueType = default(UValueType);
			// One for the "out" variable, too.
			UValueType outUValueType = default(UValueType);
			// Perform the number of calls requested, using the generator.
			Int32 iterationNumber = -1;
			while(++iterationNumber < callerObject.NumCallsOnThread) {
				// Generate the rn. Note we can capture the output value directly,
				// since the generator is defined as an IAuditingGenerator<UValueType>.
				uValueType = generator.Next();
				// Now wrap it in the RVT.
				randomRVT.Value = uValueType;
				// The nice thing is that we can always call ConvertNumber to produce
				// an arbitrary Type, no matter what IAuditingGenerator<U> uses for "U".
				// Let's try a single-precision float, shall we?
				System.Single testSingle
					= (System.Single)generator.ConvertNumber(typeof(System.Single));
				// Issue the call.
				collision = callerObject.Caller(callerObject.m_target,
					randomRVT, callerObject.Op, out outUValueType);
				// Indicate a collision on the console.
				if(collision)
					Console.WriteLine("Collision with Thread: \"{0}\"", threadName);
				// We report our status to the TestRunner as the iteration number.
				callerObject.m_statusRegister = iterationNumber;
			}
			// We give a printout of our final iteration count.
			Console.WriteLine("Thread: \"{0}\" Stopping after iteration#: " + iterationNumber.ToString(),
				threadName);
		}
		/// <summary>
		/// This is a CallerProcess for IRVT's. It is almost the same as the
		/// previous one, except it has delays in the processing loop to handle
		/// Thread-specific delays for our "WorkerProcessControl" demo. This method
		/// also allows the TestRunner to issue control commands through the CallerObject.
		/// This is the last one - we promise!!
		/// </summary>
		/// <param name="threadObject">
		/// This object must be a <see cref="IRVTConcurrentOpCallerObject&lt;UValueType&gt;"/>.
		/// </param>
		/// <remarks>
		/// We use delays outside of the Op delegate, up here in the CallerProcess.
		/// Hopefully, we've convinced ourselves by now that "lock" really locks and
		/// we don't need the delays to create collisions anymore. Up here in the
		/// CallerProcess, we use it to simulate Thread processing delays to demonstrate
		/// Thread loading and control issues.
		/// </remarks>
		public static void IRVTDelayedConcurrentCallerProcess<UValueType>(System.Object threadObject)
			where UValueType : struct
		{
			// A bool needed to report a collision.
			bool collision = false;
			// This cast will generate an exception if we don't have the correct
			// type of CallerObject coming in.
			IRVTConcurrentOpCallerObject<UValueType> callerObject
				= (IRVTConcurrentOpCallerObject<UValueType>)threadObject;
			// For reporting on our currently executing Thread.
			string threadName = Thread.CurrentThread.Name;
			// Fetch the generators from the Thread data.
			IAuditingGenerator<UValueType> numberGenerator
				= callerObject.NumberGenerator;
			// We know the delay generator always has to be Int32.
			IAuditingGenerator<Int32> delayGenerator
				= callerObject.DelayGenerator;
			// We need something wearing IReferencedValueType<UValueType> to wrap
			// rn's. A default ReferencedValueType<UValueType> is fine.
			IReferencedValueType<UValueType> randomRVT
				= new ReferencedValueType<UValueType>();
			// Need a UValueType to receive a converted copy of the rn.
			UValueType uValueType = default(UValueType);
			// One for the "out" variable, too.
			UValueType outUValueType = default(UValueType);
			// Perform the number of calls requested, using the generator.
			Int32 iterationNumber = -1;
			// In this case, we abstract the loop control - just a little bit.
			// Note, though, we could have put the composite loop test entirely
			// into ThreadStopNow.
			while((!(callerObject.ThreadStopNow))
				&& (++iterationNumber < callerObject.NumCallsOnThread)) {
				// Generate the delay and use it in Delay().
				Delay(delayGenerator.Next());
				// Generate the random data.
				uValueType = numberGenerator.Next();
				// Now wrap it in the RVT.
				randomRVT.Value = uValueType;
				// Issue the call.
				collision = callerObject.Caller(callerObject.m_target,
					randomRVT, callerObject.Op, out outUValueType);
				// Indicate a collision on the console.
				if(collision)
					Console.WriteLine("Collision with Thread: \"{0}\"", threadName);
				// We report our status as the iteration number.
				callerObject.m_statusRegister = iterationNumber;
			}
			// We give a printout of our final iteration count.
			Console.WriteLine("Thread: \"{0}\" Stopping after iteration#: " + iterationNumber.ToString(),
				threadName);
			// Tells whether we stopped early.
			if(callerObject.ThreadStopNow)
				Console.WriteLine("STOP command received by Thread: \"{0}\" ",
					threadName);
		}
		#endregion // Worker Thread Processes
		#region Callers for Atomic Delegates
		/// <summary>
		/// Caller for an Int32 that uses a "retry loop" for synchonized concurrent
		/// access to a shared data item.
		/// </summary>
		/// <param name="target">
		/// This is the <see cref="System.Int32"/> target that is designed to be
		/// modified by multiple Threads or processes. It is a ValueType and thus,
		/// must be passed by reference.
		/// </param>
		/// <param name="source">
		/// This is the source value that will be used to somehow modify the target
		/// by the OP delegate. 
		/// </param>
		/// <param name="oP">
		/// This is a delegate for the binary operation to be performed on the
		/// source and destination.
		/// </param>
		/// <param name="lastValue">
		/// A copy of the <see cref="System.Int32"/> value written to the target.
		/// </param>
		/// <returns>
		/// <c>true</c> if a Thread collision has been detected.
		/// </returns>
		public static System.Boolean RetryLOOPPseudoAtomicInt32OpCaller(ref System.Int32 target,
			System.Int32 source, Int32Op oP, out System.Int32 lastValue)
		{
			// This variable stores a local copy of the original value of the target
			// that is read before the OP and the atomic exchange. It is used to
			// compare with the most recently fetched value from the atomic exchange
			// to see if it has been modified by another Thread.
			System.Int32 workingValue = target;
			// This variable stores a local copy of the most recent value of the
			// target as returned from the atomic exchange operation.
			System.Int32 lastUpdatedValue = target;
			// This variable will be set to <c>true</c> if we undergo a collision.
			System.Boolean hadCollision = false;
			// Result for our OP;
			Int32 opResult;

			// Repeat until we get no more collisions.
			do {
				// Set the working value to the last update.
				workingValue = lastUpdatedValue;
				// Perform the OP on the local opResult variable.
				opResult = workingValue;
				oP(ref opResult, source);
				// Make the switch only if the target has not changed from our
				// last workingValue. lastUpdatedValue always receives the current
				// value of target as returned by CompareExchange.
				lastUpdatedValue
					= Interlocked.CompareExchange(ref target, opResult, workingValue);
				// Report progress if we want....
				if(QATester_MultiProcessing_Testdata.s_reportToScreen)
					Console.WriteLine("  >Processed a Number on ManagedThreadID #: "
						+ Thread.CurrentThread.ManagedThreadId.ToString());
				lastValue = lastUpdatedValue;
				// If the two values are different, this means that we had a collision.
				if(lastUpdatedValue != workingValue) hadCollision = true;
				// Keep LOOPing and RETRYing if we have had a collision.
			} while(lastUpdatedValue != workingValue);
			return hadCollision;
		}
		/// <summary>
		/// Generic caller useful for an open Generic RVT. This is a caller that
		/// accepts a specific Type, not just its <see cref="IReferencedValueType&lt;UValueType&gt;"/>
		/// interface.
		/// <typeparam name="T">
		/// This is the actual Type implementing IRVT.
		/// </typeparam>
		/// <typeparam name="UValueType">
		/// This is the contained Type that the <see typeparamref="T"/> manipulates
		/// and provides access to through the IRVT interface.
		/// </typeparam>
		/// <param name="target">
		/// The target <see typeparamref="T"/>-valued Type that is to be modified.
		/// This is the first argument to the <see paramref="oP"/> delegate.
		/// </param>
		/// <param name="source">
		/// The source <see typeparamref="T"/>-valued Type that is to be used to modify
		/// the target. This is the first argument to the <see paramref="oP"/> delegate.
		/// </param>
		/// <param name="oP">
		/// The <see typeparamref="T"/>-valued OP that is to be performed on the
		/// source and target.
		/// </param>
		/// <param name="lastValue">
		/// A copy of the <see typeparamref="UValueType"/> value written inside the
		/// target <see typeparamref="T"/>.
		/// </param>
		/// <returns>
		/// <c>true</c> if a Thread collision has been detected.
		/// </returns>
		/// </summary>
		/// <remarks>
		/// Note that target does not need to be passed by reference, since we
		/// are modifying the internal struct of the target class, not the
		/// class instance reference itself.
		/// </remarks>
		public static System.Boolean RVTTypeConcurrentOpCaller<T, UValueType>(T target,
			T source, RVTOp<T, UValueType> oP, out UValueType lastValue)
			where T : class, IReferencedValueType<UValueType>
			where UValueType : struct
		{
			// These variables are working storage for our internal Generic
			// UValueType.
			UValueType oldValue;
			UValueType opResult;
			bool hadCollision = false;
			// Lock the RVT and perform the OP.
			lock(target) {
				// Save the last value.
				oldValue = target.Value;
				// Do the OP.
				opResult = oP(target, source);
				lastValue = opResult;
			}
			// Report progress if we want....
			if(QATester_MultiProcessing_Testdata.s_reportToScreen)
				Console.WriteLine("  >Processed a Number on ManagedThreadID #: "
					+ Thread.CurrentThread.ManagedThreadId.ToString());
			// If the two values are different, this means that we had a collision.
			// Note that you should define a Type-specific "Equals" on your own
			// closed Types. CLR must do it through reflection on arbitrary structs,
			// but you don't if you have a specific closure!! This will also generate
			// a BOXing operation. Sometimes better to provide Equals(UValueType,UValueType),
			// since you then don't have to be worried about overloading HashCode(), too.
			// 
			// This obviously should never be true, since we have the target locked.
			if(!Equals(oldValue, opResult)) hadCollision = true;
			return hadCollision;
		}
		/// <summary>
		/// Generic caller useful for a Generic IRVT. See the RVT caller for details.
		/// This one handles RVTs only by their interface.
		/// </summary>
		/// <typeparam name="UValueType">
		/// This is the contained Type that the IRVT manipulates.
		/// </typeparam>
		/// <param name="target">
		/// Target of the OP delegate. See the RVT caller for details. Same, except
		/// now we work on the internal <see typeparamref="UValueType"/> through
		/// its Interface. Note that this method argument can still be passed by
		/// value, (not with an "out" keyword), since an Interface is a ReferenceType.
		/// </param>
		/// <param name="source">
		/// See the RVT caller for details. Same, except now we work on the internal
		/// <see typeparamref="UValueType"/>.
		/// </param>
		/// <param name="oP">
		/// The OP that operates on the raw <see paramref="UValueType"/>s.
		/// </param>
		/// <param name="lastValue">
		/// Copy of the last <see paramref="UValueType"/> output on the target.
		/// </param>
		/// <returns>
		/// <c>true</c> if a Thread collision has been detected.
		/// </returns>
		public static System.Boolean IRVTConcurrentOpCaller<UValueType>(
			IReferencedValueType<UValueType> target, IReferencedValueType<UValueType> source,
				IRVTOp<UValueType> oP, out UValueType lastValue)
				where UValueType : struct
		{
			// These variables are working storage for our internal Generic
			// UValueType.
			UValueType oldValue;
			UValueType opResult;
			// This one has the usual purpose - it should never be true in this
			// method, however....
			bool hadCollision = false;
			// Lock the IRVT's underlying System.Object and perform the OP.
			lock(target) {
				// Save the last value.
				oldValue = target.Value;
				// Do the OP.
				opResult = oP(target, source);
				lastValue = opResult;
			}
			// Report progress if we want....
			if(QATester_MultiProcessing_Testdata.s_reportToScreen)
				Console.WriteLine("  >Processed a Number on ManagedThreadID #: "
					+ Thread.CurrentThread.ManagedThreadId.ToString());
			// If the two values are different, this means that we had a
			// collision. Note that you should define a Type-specific "Equals"
			// on your own UValueType since the CLR does it through reflection
			// on arbitrary structs (slow), but you don't have to if you have
			// a specific concrete closure!! Note also, that we will be BOXing
			// again if we use something expecting a System.Object, so you
			// probably would want to define an UValueType.Equals(UValueType)
			// ala an implicit interface implementation of IEquatable<UValueType>
			// if you needed an equality comparison.
			//
			// This obviously should never be true, since we have the target locked.
			if(!Equals(oldValue, opResult)) hadCollision = true;
			return hadCollision;
		}
		/// <summary>
		/// This caller tries to demonstrate what's wrong with thinking that an OP wrapping
		/// an atomic OP constitutes an atomic OP. This one does the locking only after the
		/// read and subsequent binary operation. It is designed to simulate the old Int32
		/// situation with RVTs and a "lock" statement as opposed to a CompareExchange.
		/// </summary>
		public static System.Boolean IRVTPseudoAtomicOpCaller<UValueType>(
			IReferencedValueType<UValueType> target, IReferencedValueType<UValueType> source,
				IRVTOp<UValueType> oP, out UValueType lastValue)
					where UValueType : struct
		{
			// This variable stores a local copy of the original value of the target
			// that is read before the OP and the atomic exchange. It is used to
			// compare with the most recently fetched value from the atomic exchange
			// to see if it has been modified by another Thread.
			UValueType workingValue = target.Value;
			// This variable stores a local copy of the most recent value of the
			// target as returned from the atomic exchange operation.
			UValueType lastUpdatedValue = workingValue;
			// This variable will be set to <c>true</c> if we undergo a collision.
			System.Boolean hadCollision = false;
			// Result for our OP - an RVT<UValueType> is fine to receive it.
			ReferencedValueType<UValueType> opResult = new ReferencedValueType<UValueType>();

			// Repeat until we get no more collisions.
			do {
				// Set the working value to the last update.
				workingValue = lastUpdatedValue;
				// Perform the OP on the local opResult variable.
				opResult.Value = workingValue;
				oP(opResult, source);
				// Make the switch only if the target has not changed from our
				// last workingValue. lastUpdatedValue always receives the current
				// value of target.
				lock(target) {
					////  Next two instructions simulate the function of CompareExchange.
					// Since the target is locked, this is an atomic operation.
					lastUpdatedValue = target.Value;
					// We assume in this test caller that any UValueType we would
					// supply overrides Equals. This is true of any CLR primitive
					// Types like Boolean, Int32, etc.. This tests to see if another
					// Thread has replaced the target with a different value before
					// we locked it.
					if(lastUpdatedValue.Equals(workingValue))
						target.Value = source.Value;
				}
				// Report progress if we want....
				if(QATester_MultiProcessing_Testdata.s_reportToScreen)
					Console.WriteLine("  >Processed a Number on ManagedThreadID #: "
						+ Thread.CurrentThread.ManagedThreadId.ToString());
				lastValue = lastUpdatedValue;
				// If the two values are different, this means that we had a collision.
				if(!Equals(lastUpdatedValue, workingValue)) hadCollision = true;
				// Keep going if we have had a collision.
			} while(!Equals(lastUpdatedValue, workingValue));
			return hadCollision;
		}
		/// <summary>
		/// Generic caller for calling <see cref="Interlocked.CompareExchange&lt;T&gt;"/>
		/// internally to update the <see paramref="target"/> after the Generic operation
		/// has been completed. The Generic CompareExchange method has a class constraint
		/// so we must use it here.
		/// See <see cref="RVTConcurrentCallerProcess&lt;T, UValueType&gt;"/> for params.
		/// </summary>
		/// <remarks>
		/// Unfortunatly, <see cref="System.Threading.Interlocked.CompareExchange&lt;T&gt;"/>
		/// uses ReferenceEquals, just like the object version. Thus, this caller is not useful,
		/// even for demonstration purposes.
		/// </remarks>
		internal static System.Boolean RetryLOOPPseudoAtomicOpCaller<T, UValueType>(ref T target,
			T source, RVTOp<T, UValueType> oP, out UValueType lastValue)
			where T : class, IReferencedValueType<UValueType>
			where UValueType : struct
		{
			// This variable stores a local copy of the original value of the target.
			// It is also used to compare with the most recently fetched value to
			// see if it has been modified by another Thread.
			T workingValue = target;
			// This variable stores a local copy of the most recent value of the target.
			T lastUpdatedValue = target;
			// This variable will be set to <c>true</c> if we encounter a collision.
			System.Boolean hadCollision = false;
			// Result for our OP;
			T opResult;

			// Repeat until we get no more collisions.
			do {
				// Set the working value to the last update.
				workingValue = lastUpdatedValue;
				// Make the switch only if the target has not changed from our
				// last working value. lastUpdatedValue always receives the current
				// value of target.
				opResult = workingValue;
				oP(opResult, source);
				lastUpdatedValue
					= Interlocked.CompareExchange(ref target, opResult, workingValue);
				if(QATester_MultiProcessing_Testdata.s_reportToScreen)
					Console.WriteLine("  >Processed a Number on ManagedThreadID #: "
						+ Thread.CurrentThread.ManagedThreadId.ToString());
				lastValue = lastUpdatedValue.Value;
				// If the two values are different, this means that we had a collision.
				if(!lastUpdatedValue.IsValueSameAs(workingValue)) hadCollision = true;
				// Keep going if we have had a collision.
			} while(!lastUpdatedValue.IsValueSameAs(workingValue));
			return hadCollision;
		}
		#endregion // Callers for Atomic Delegates.
		#region Test Operations Implementing OP Delegates
		#region Int32 Ops
		/// <summary>
		/// The default operation that just writes the source to the target.
		/// </summary>
		/// <param name="target">
		/// The number to be overwritten.
		/// </param>
		/// <param name="source">
		/// The number to be written to the target.
		/// </param>
		/// <returns>
		/// Original value of the target.
		/// </returns>
		public static Int32 Int32ReplaceOp(ref Int32 target, Int32 source)
		{
			Int32 oldTarget = target;
			// Just move it over.
			target = source;
			return oldTarget;
		}
		/// <summary>
		/// The default operation that just writes the source to the target after
		/// a delay that is derived from the static delay generator. The use of this
		/// OP assumes that we don't care about a fixed sequence of delays being
		/// associated with any particular Thread if the OP is being called on
		/// multiple Threads. If we care, then a separate generator must be associated
		/// with each OP delegate. We don't really need this in most of our tests.
		/// </summary>
		/// <param name="target">
		/// The number to be overwritten.
		/// </param>
		/// <param name="source">
		/// The number to be written to the target.
		/// </param>
		/// <returns>
		/// Original value of the target.
		/// </returns>
		public static Int32 Int32DelayedReplaceOp(ref Int32 target, Int32 source)
		{
			Int32 oldTarget = target;
			Int32 delay = s_Int32RngDelays.Next();
			if(delay > 0) Delay(delay);
			// Just move it over.
			target = source;
			return oldTarget;
		}
		/// <summary>
		/// This operation writes the sum of source and target to the target.
		/// </summary>
		/// <param name="target">
		/// The number to be overwritten.
		/// </param>
		/// <param name="source">
		/// The number to be added to the target.
		/// </param>
		/// <returns>
		/// Original value of the target.
		/// </returns>
		public static Int32 Int32AddOp(ref Int32 target, Int32 source)
		{
			Int32 oldTarget = target;
			// Just move it over.
			target += source;
			return oldTarget;
		}
		/// <summary>
		/// This operation writes the sum of source and target to the target
		/// with a delay. Same deal as DelayedReplace.......
		/// </summary>
		/// <param name="target">
		/// The number to be overwritten.
		/// </param>
		/// <param name="source">
		/// The number to be added to the target.
		/// </param>
		/// <returns>
		/// Original value of the target.
		/// </returns>
		public static Int32 Int32DelayedAddOp(ref Int32 target, Int32 source)
		{
			Int32 oldTarget = target;
			Int32 delay = s_Int32RngDelays.Next();
			if(delay > 0) Delay(delay);
			// Just move it over.
			target += source;
			return oldTarget;
		}
		/// <summary>
		/// This operation raises the target to the exponent represented 
		/// by <see paramref="source"/>.
		/// </summary>
		/// <param name="target">
		/// The number to be overwritten.
		/// </param>
		/// <param name="source">
		/// The number of times that the target is to be multiplied by itself.
		/// </param>
		/// <returns>
		/// Original value of the target.
		/// </returns>
		public static Int32 Int32ExpOp(ref Int32 target, Int32 source)
		{
			Int32 oldTarget = target;
			Int32 workingVar = target;
			for(int i = 0; i < source; i++)
				workingVar *= oldTarget;
			// Just move it over.
			target = workingVar;
			return oldTarget;
		}
		#endregion // Int32 Ops
		#region Open RVTOps
		/// <summary>
		/// This operation just writes the source to the target after
		/// a delay that is derived from the static delay generator. The use of this
		/// Op assumes that we don't care about a fixed sequence of delays being
		/// associated with any particular Thread if the Op is being called on
		/// multiple Threads. If we care, then a separate generator must be associated
		/// with each Op delegate. We don't really need this in most of our tests.
		/// This is really the only binary OP that can be sensibly defined for a
		/// Generic <see cref="ReferencedValueType&lt;UValueType&gt;"/>.
		/// </summary>
		/// <param name="target">
		/// The number to be overwritten.
		/// </param>
		/// <param name="source">
		/// The number to be written to the target.
		/// </param>
		/// <returns>
		/// Original value of the target.
		/// </returns>
		public static UValueType RVTDelayedReplaceOp<T, UValueType>(T target, T source)
			where T : class, IReferencedValueType<UValueType>
			where UValueType : struct
		{
			UValueType oldTarget = target.Value;
			Int32 delay = s_Int32RngDelays.Next();
			if(delay > 0) Delay(delay);
			// Just move it over.
			target.SwapValues(source);
			return oldTarget;
		}
		/// <summary>
		/// This operation just writes the source to the target after
		/// a delay that is derived from the static delay generator. The use of this
		/// OP assumes that we don't care about a fixed sequence of delays being
		/// associated with any particular Thread if the OP is being called on
		/// multiple Threads. If we care, then a separate generator must be associated
		/// with each OP delegate. We don't really need this in most of our tests.
		/// This is really the only binary OP that can be sensibly defined for a
		/// Generic <see cref="IReferencedValueType&lt;UValueType&gt;"/>.
		/// </summary>
		/// <param name="target">
		/// The number to be overwritten.
		/// </param>
		/// <param name="source">
		/// The number to be written to the target.
		/// </param>
		/// <returns>
		/// Original value of the target.
		/// </returns>
		public static UValueType IRVTDelayedReplaceOp<UValueType>(
			IReferencedValueType<UValueType> target, IReferencedValueType<UValueType> source)
			where UValueType : struct
		{
			UValueType oldTarget = target.Value;
			Int32 delay = s_Int32RngDelays.Next();
			if(delay > 0) Delay(delay);
			// Just move it over.
			target.Value = source.Value;
			return oldTarget;
		}
		/// <summary>
		/// Same thing, but no delay.......
		/// </summary>
		/// <param name="target">
		/// The number to be overwritten.
		/// </param>
		/// <param name="source">
		/// The number to be written to the target.
		/// </param>
		/// <returns>
		/// Original value of the target.
		/// </returns>
		public static UValueType IRVTReplaceOp<UValueType>(
			IReferencedValueType<UValueType> target, IReferencedValueType<UValueType> source)
			where UValueType : struct
		{
			UValueType oldTarget = target.Value;
			// Just move it over.
			target.Value = source.Value;
			return oldTarget;
		}
		#endregion // Open RVTOps
		#endregion // Test Operations Implementing OP Delegates
		#region Utility Methods
		/// <summary>
		/// Method that does some OPs to simulate processing delay.
		/// </summary>
		/// <param name="delay">
		/// The number of time units to delay.
		/// </param>
		public static void Delay(Int32 delay)
		{
			Int32 numIterations = 10000;
			Int32 workingVar = 0;
			for(int i = 0; i < delay * numIterations; i++)
				workingVar *= workingVar;
		}
		#endregion // Utility Methods
		#endregion // Static Test Methods
		#endregion // Static Class Methods
	}
	#endregion
	#region Tests
	/// <summary>
	/// Level 2 tests for functions in AtomicUtils. These are attributed for Nunit as
	/// level 2 since they take some time due to delays introduced for threading.
	/// </summary>
	[TestFixture]
	[Category(QAUtils.TestLevel2Name)]
	public class QATester_AtomicUtils_2
	{
		//// Here follows a number of class-level data objects that are used for
		//// The various tests.
		//
		//// These are for the basic Int32 tests.
		///////////////////////////////////////////////////////////////////////
		// CallerObject for the Int32 RetryLoop caller calling the default OP - no delay.
		Int32ConcurrentOpCallerObject m_RetryLoopInt32ReplaceCallerObject;
		// CallerObject for the Int32 RetryLoop caller calling the default OP - random OP delay.
		Int32ConcurrentOpCallerObject m_RetryLoopInt32DelayedReplaceCallerObject;
		// CallerObject for the Int32 RetryLoop caller calling the add OP - no delay.
		Int32ConcurrentOpCallerObject m_RetryLoopInt32AddCallerObject;
		// CallerObject for the Int32 RetryLoop caller calling the exp OP - no delay.
		Int32ConcurrentOpCallerObject m_RetryLoopInt32ExpCallerObject;
		//// These are for the IRVT closed as an Int32.
		///////////////////////////////////////////////////////////////////////
		// CallerObject with the delayed replace OP.
		IRVTConcurrentOpCallerObject<Int32> m_IRVTCallerObjectAsInt32DelayedReplace;
		// Set up a CallerObject for the non-atomic caller.
		IRVTConcurrentOpCallerObject<Int32> m_IRVTPseudoAtomicCallerObjectAsInt32DelayedReplace;
		//// For the RVTConcurrentCaller test.
		///////////////////////////////////////////////////////////////////////
		// CallerObject with the delayed replace OP.
		RVTTypeConcurrentOpCallerObject<ReferencedValueType<Int32>, Int32>
			m_RVTTypeCallerObjectAsInt32DelayedReplace;
		//// These are for the RVT closed as an Int32.
		///////////////////////////////////////////////////////////////////////
		// These are class-level variables that are used to hold targets for the Threads.
		ReferencedValueType<Int32> multiAccessTargetInt32RVT = new ReferencedValueType<Int32>();
		///////////////////////////////////////////////////////////////////////
		//// For the WorkerProcessControl test.
		// CallerObject with the replace OP. This is the default CallerObject.
		IRVTConcurrentOpCallerObject<Int32> m_IRVTCallerObjectAsInt32Replace;
		// CallerObject with the replace OP - this one is for a special
		// Main control Thread.
		IRVTConcurrentOpCallerObject<Int32> m_IRVTCallerObjectAsInt32Replace_Main;
		// CallerObject with the replace OP - this one is for a special
		// Worker Thread.
		IRVTConcurrentOpCallerObject<Int32> m_IRVTCallerObjectAsInt32Replace_LongRunningThread;
		// Same thing here....
		IRVTConcurrentOpCallerObject<Int32> m_IRVTCallerObjectAsInt32Replace_SlowRunningThread;

		/// <summary>
		/// Obligatory default constructor (for NUnit, that is). This one actually
		/// does something :-)
		/// </summary>
		public QATester_AtomicUtils_2()
		{
			// Here we build CallerObjects for the Thread process. These have the standard
			// versions of a delegate for the caller, a delegate for the OP, random
			// data generator, random delay generator and work out of the static
			// target int. This one takes the default OP (the replacement OP) with no delay.
			// 10 iterations.
			m_RetryLoopInt32ReplaceCallerObject = new Int32ConcurrentOpCallerObject(
				QATester_MultiProcessing_Testdata.RetryLOOPPseudoAtomicInt32OpCaller,
					QATester_MultiProcessing_Testdata.Int32ReplaceOp, 10,
					QATester_MultiProcessing_Testdata.s_Int32RngNumbers,
					QATester_MultiProcessing_Testdata.s_Int32RngDelays,
					QATester_MultiProcessing_Testdata.s_multiaccessInt32Target);
			// This one takes the Delayed delegate, but is otherwise the same.
			m_RetryLoopInt32DelayedReplaceCallerObject = new Int32ConcurrentOpCallerObject(
				QATester_MultiProcessing_Testdata.RetryLOOPPseudoAtomicInt32OpCaller,
					QATester_MultiProcessing_Testdata.Int32DelayedReplaceOp, 10,
					QATester_MultiProcessing_Testdata.s_Int32RngNumbers,
					QATester_MultiProcessing_Testdata.s_Int32RngDelays,
					QATester_MultiProcessing_Testdata.s_multiaccessInt32Target);
			// This one takes the adder delegate, but is otherwise the same as the first.
			m_RetryLoopInt32AddCallerObject = new Int32ConcurrentOpCallerObject(
				QATester_MultiProcessing_Testdata.RetryLOOPPseudoAtomicInt32OpCaller,
					QATester_MultiProcessing_Testdata.Int32AddOp, 10,
					QATester_MultiProcessing_Testdata.s_Int32RngNumbers,
					QATester_MultiProcessing_Testdata.s_Int32RngDelays,
					QATester_MultiProcessing_Testdata.s_multiaccessInt32Target);
			// This one takes the exponentiation delegate, but is otherwise the same as the first.
			m_RetryLoopInt32ExpCallerObject = new Int32ConcurrentOpCallerObject(
				QATester_MultiProcessing_Testdata.RetryLOOPPseudoAtomicInt32OpCaller,
					QATester_MultiProcessing_Testdata.Int32ExpOp, 10,
					QATester_MultiProcessing_Testdata.s_Int32RngNumbers,
					QATester_MultiProcessing_Testdata.s_Int32RngDelays,
					QATester_MultiProcessing_Testdata.s_multiaccessInt32Target);
			// This is for the GenericRVTCaller experiment. This is a CallerObject
			// for the Thread process, designed to be passed to an RVT - based Caller.
			// This has the standard version of a delegate for the caller, a delegate
			// for the OP, random delay generator and work out of a local target int.
			// This one takes the default IRVTOp (the replacement OP) with delay.
			// 10 iterations.
			//
			// We first have to make an IAuditingGenerator<T>, because that's what
			// The CallerObject uses.
			m_RVTTypeCallerObjectAsInt32DelayedReplace
				= new RVTTypeConcurrentOpCallerObject<ReferencedValueType<Int32>,Int32>(
					QATester_MultiProcessing_Testdata.RVTTypeConcurrentOpCaller<ReferencedValueType<Int32>, Int32>,
					QATester_MultiProcessing_Testdata.RVTDelayedReplaceOp<ReferencedValueType<Int32>,Int32>,
					10, QATester_MultiProcessing_Testdata.s_Int32RngNumbers,
					QATester_MultiProcessing_Testdata.s_Int32RngDelays,
					multiAccessTargetInt32RVT);
			// The following are CallerObjects for the Thread process, this time designed
			// to be passed to an IRVT. These have the standard versions of a delegate
			// for the caller, a delegate for the OP, random data generator, random delay
			// generator and work out of a local target int. This one takes the
			// default IRVTOp (the replacement OP) with delay. 10 iterations.
			m_IRVTCallerObjectAsInt32DelayedReplace
				= new IRVTConcurrentOpCallerObject<Int32>(
					QATester_MultiProcessing_Testdata.IRVTConcurrentOpCaller<Int32>,
					QATester_MultiProcessing_Testdata.IRVTDelayedReplaceOp<Int32>,
					10, QATester_MultiProcessing_Testdata.s_Int32RngNumbers,
					QATester_MultiProcessing_Testdata.s_Int32RngDelays,
					multiAccessTargetInt32RVT);
			// Same thing again, but using the non-atomic caller.
			m_IRVTPseudoAtomicCallerObjectAsInt32DelayedReplace
				= new IRVTConcurrentOpCallerObject<Int32>(
					QATester_MultiProcessing_Testdata.IRVTPseudoAtomicOpCaller<Int32>,
					QATester_MultiProcessing_Testdata.IRVTDelayedReplaceOp<Int32>,
					10, QATester_MultiProcessing_Testdata.s_Int32RngNumbers,
					QATester_MultiProcessing_Testdata.s_Int32RngDelays,
					multiAccessTargetInt32RVT);
			///////////////////////////////////////////////////////////////////
			// In this section, we set up for the Worker Thread "control"
			// experiment that we run in test "WorkerProcessControl". We set up
			// data for a a Main Thread and some Workers.
			///////////////////////////////////////////////////////////////////
			// This is the default CallerObject with non-delayed replace.
			m_IRVTCallerObjectAsInt32Replace
				= new IRVTConcurrentOpCallerObject<Int32>(
					QATester_MultiProcessing_Testdata.IRVTConcurrentOpCaller<Int32>,
					QATester_MultiProcessing_Testdata.IRVTReplaceOp<Int32>,
					10, QATester_MultiProcessing_Testdata.s_Int32RngNumbers,
					QATester_MultiProcessing_Testdata.s_Int32RngDelays,
					multiAccessTargetInt32RVT);
			// We are now going to make a separate CallerObject for a Main Thread to
			// show how the test runners can set up different Threads with different
			// characteristics. We can't do much with changing the OP, since IRVT's
			// are manipulators of a rather abstract nature. It would be entirely
			// possible, however, to define additional interfaces that provided
			// additional operations (arirhmetic, comparisons, who knows what else).
			// We don't do so here. We can, however, change random number generators
			// and change other things. In particular, we kill two birds with one
			// stone and set ControlRegister on the Main Thread to exercise some
			// control over Worker Thread operation in addition to changing iterations
			// and delays on Threads. See IRVTTestRunner() for what we do with it
			// the ControlRegister and StatusRegister internally.
			//
			// First build a new generator for Main with shorter delays. 
			// Seed 10000, Delays range from 1 to 100 - no special OP needed,
			// no logging. Delays are short because we want Main to finish
			// early so it can manipulate Worker Threads before they finish.
			// Initialize the generator with a zero data state (we actually
			// don't use it, so we don't care). Note that these all use the
			// non-delayed version of the replace OP, since delays are incorporated
			// in the Thread process in IRVTDelayedConcurrentCallerThreadProc().
			AuditingRNGenerator<Int32> new_Int32RngDelays
				= new AuditingRNGenerator<Int32>(10000, 1, 100, null, 0, false);
			// This is the CallerObject for the Main Thread process. We build it
			// with the delay generator we just created - otherwise it's the same.
			m_IRVTCallerObjectAsInt32Replace_Main
				= new IRVTConcurrentOpCallerObject<Int32>(
					QATester_MultiProcessing_Testdata.IRVTConcurrentOpCaller<Int32>,
					QATester_MultiProcessing_Testdata.IRVTReplaceOp<Int32>,
					10, QATester_MultiProcessing_Testdata.s_Int32RngNumbers,
					new_Int32RngDelays, multiAccessTargetInt32RVT);
			// We also set it's ControlRegister to -1. We'll use this to demonstrate
			// how to control Threads. The testrunner "IRVTTestRunner" uses this
			// internally to perform that demonstration.
			m_IRVTCallerObjectAsInt32Replace_Main.m_controlRegister = -1;
			// We spawn a CallerObject for a second Thread to run under control
			// of Main. We would like this object to specify a large number of
			// iterations - just to show how to set up a single Worker Thread that
			// will definately have to be stopped early. We spawn it with an initial
			// state of 1234567 from the CallerObject we built for Main.
			m_IRVTCallerObjectAsInt32Replace_LongRunningThread
				= m_IRVTCallerObjectAsInt32Replace_Main.SpawnCallerObject(1234567);
			// We would like to make this Thread run much longer than the others,
			// so we'll set more iterations. It is already going to run much
			// faster, since we are spawning Main's generator with its shorter
			// delay. We decreased delays by a factor of 10 and increased iterations
			// by a factor of 100 - let's hope it works :-)
			m_IRVTCallerObjectAsInt32Replace_LongRunningThread.m_numCallsOnThread = 1000;
			// We create a CallerObject for a second Worker Thread to run under control
			// of Main. We would like this CallerObject to specify a long delay - we
			// want the Main Thread program to have to wait for this Thread to complete
			// a certain number of operations (only three) - this Thread will be the
			// laggard in this test.
			//
			// First create a new generator - fixed delay of 2000.
			new_Int32RngDelays
				= new AuditingRNGenerator<Int32>(10001, 2000, 2000, null, 0, false);
			// Run 10 operations on this Thread. Keep in mind that each OP will take
			// a long time.
			m_IRVTCallerObjectAsInt32Replace_SlowRunningThread
				= new IRVTConcurrentOpCallerObject<Int32>(
					QATester_MultiProcessing_Testdata.IRVTConcurrentOpCaller<Int32>,
					QATester_MultiProcessing_Testdata.IRVTReplaceOp<Int32>,
					10, QATester_MultiProcessing_Testdata.s_Int32RngNumbers,
					new_Int32RngDelays, multiAccessTargetInt32RVT);
		}
		/// <summary>
		/// </summary>
		[TestFixtureSetUp]
		public void TestFixtureSetup()
		{
			// Shut off reporting for autotests under Nunit. The tests in this file
			// all just scroll to the screen, so if you uncomment this, the tests
			// are totally useless. Someday, if somebody wants to put quantitative
			// tests in here then this is one way to shut off the screen ....
			//s_reportToScreen = false;
		}
		/// <summary>
		/// </summary>
		[TestFixtureTearDown]
		public void TestFixtureTearDown()
		{
		}
		/// <summary>
		/// This test runs the
		/// <see cref="QATester_MultiProcessing_Testdata.RetryLOOPPseudoAtomicInt32OpCaller"/>
		/// with multiple Threads to demonstrate that it does not provide atomic operation. You
		/// might see a couple of collisions in the test.
		/// </summary>
		[Test(Description = "Level 2 series a tests for RetryLoopInt32PseudoAtomicOpCaller")]
		public void QATester_RunTest_RetryLoopInt32PseudoAtomicOpCaller_a()
		{
			Console.WriteLine("Running RetryLoopInt32PseudoAtomicOpCaller_a");
			// We don't want any old Threads running or old data.
			QATester_MultiProcessing_Testdata.ClearThreads();
			// We also want the standard default settings for this test.
			QATester_MultiProcessing_Testdata.ResetData();
			// Set the number of Threads.
			QATester_MultiProcessing_Testdata.s_numThreadsInUse = 10;
			QATester_MultiProcessing_Testdata.Int32TestRunner(m_RetryLoopInt32ReplaceCallerObject, true);
		}
		/// <summary>
		/// This test runs the
		/// <see cref="QATester_MultiProcessing_Testdata.RetryLOOPPseudoAtomicInt32OpCaller"/>
		/// with multiple Threads to demonstrate that it does not provide atomic operation. This
		/// time we use delays - things get much worse.
		/// </summary>
		[Test(Description = "Level 2 series b tests for RetryLoopInt32PseudoAtomicOpCaller")]
		public void QATester_RunTest_RetryLoopInt32PseudoAtomicOpCaller_b()
		{
			// Took out "b" for the article printout.
			// This is the one we use for the article's first printout.
			// Console.WriteLine("Running RetryLoopInt32PseudoAtomicOpCaller_b");
			Console.WriteLine("Running RetryLoopInt32PseudoAtomicOpCaller");
			// Usual setup jazz.
			QATester_MultiProcessing_Testdata.ClearThreads();
			QATester_MultiProcessing_Testdata.ResetData();
			// Set the number of Threads.
			QATester_MultiProcessing_Testdata.s_numThreadsInUse = 3;
			QATester_MultiProcessing_Testdata.Int32TestRunner(m_RetryLoopInt32DelayedReplaceCallerObject, true);
		}
		/// <summary>
		/// This test runs the
		/// <see cref="QATester_MultiProcessing_Testdata.IRVTConcurrentOpCaller"/>
		/// with multiple Threads to test it for atomic operation. In this case we
		/// use delays. We want to demonstrate the obvious - access to a locked
		/// object is thread-safe. The caller is closed as an Int32. This test run
		/// passes no Thread data (null), so it will be created internally based
		/// on Thread Id's for generator seeds.
		/// </summary>
		[Test(Description = "Level 2 series a tests for IRVTConcurrentCaller")]
		public void QATester_RunTest_IRVTConcurrentCaller_a()
		{
			Console.WriteLine("Running IRVTConcurrentCaller_a");
			// Usual setup jazz.
			QATester_MultiProcessing_Testdata.ClearThreads();
			QATester_MultiProcessing_Testdata.ResetData();
			// Set the number of Threads locally.
			Int32 numSpawnedThreadsInUse = 10;
			QATester_MultiProcessing_Testdata.IRVTTestRunner<Int32>(
				QATester_MultiProcessing_Testdata.IRVTConcurrentCallerProcess<Int32>,
					m_IRVTCallerObjectAsInt32DelayedReplace,
						null, numSpawnedThreadsInUse, true);
		}
		/// <summary>
		/// This test runs the
		/// <see cref="QATester_MultiProcessing_Testdata.RVTTypeConcurrentOpCaller"/>.
		/// We want to test the operation of a Thread process with the Caller designed
		/// to take an actual full constructed Type, not just the IRVT Interface.
		/// Working with the IRVT only is usually a better way to go, but sometimes
		/// the RVT-based one is needed. Again, the Generic is just closed on a simple
		/// Int32. See ReferencedValueTypes.cs for the more complicated stuff.
		/// </summary>
		[Test(Description = "Level 2 series a tests for RVTConcurrentCaller")]
		public void QATester_RunTest_RVTConcurrentCaller_a()
		{
			Console.WriteLine("Running RVTConcurrentCaller_a");
			// Usual setup jazz.
			QATester_MultiProcessing_Testdata.ClearThreads();
			QATester_MultiProcessing_Testdata.ResetData();
			// Set the number of Threads locally.
			Int32 numSpawnedThreadsInUse = 10;
			// We are going to send in a null ThreadData array. We already demonstrated
			// how to do customized Threads in WorkerProcessControl_a. All Thread
			// CallerObject's (10 in use here - no Main Thread) will be synthesized
			// internally by the test runner.
			RVTTypeThreadData<ReferencedValueType<Int32>, Int32>[] threadDataArray = null;
			QATester_MultiProcessing_Testdata.RVTTypeTestRunner<ReferencedValueType<Int32>,Int32>(
				m_RVTTypeCallerObjectAsInt32DelayedReplace, threadDataArray,
					numSpawnedThreadsInUse, true);
		}
		/// <summary>
		/// This test runs the
		/// <see cref="QATester_MultiProcessing_Testdata.IRVTPseudoAtomicOpCaller"/>.
		/// to test it for atomic operation. Pretty much the same as the
		/// previous test. Again, we want to demonstrate the obvious - access to
		/// an object that is not locked all the way through the access is NOT
		/// thread-safe. The caller is closed as an Int32, once again. You should
		/// see collisions.
		/// </summary>
		[Test(Description = "Level 2 series a tests for IRVTPseudoAtomicConcurrentCaller")]
		public void QATester_RunTest_IRVTPseudoAtomicConcurrentCaller_a()
		{
			Console.WriteLine("Running IRVTPseudoAtomicConcurrentCaller_a");
			// Usual setup jazz.
			QATester_MultiProcessing_Testdata.ClearThreads();
			QATester_MultiProcessing_Testdata.ResetData();
			// Set the number of Threads locally.
			Int32 numSpawnedThreadsInUse = 10;
			QATester_MultiProcessing_Testdata.IRVTTestRunner<Int32>(
				QATester_MultiProcessing_Testdata.IRVTConcurrentCallerProcess<Int32>,
					m_IRVTPseudoAtomicCallerObjectAsInt32DelayedReplace, null, numSpawnedThreadsInUse, true);
		}
		/// <summary>
		/// This test again runs the 
		/// <see cref="QATester_MultiProcessing_Testdata.IRVTConcurrentOpCaller"/>
		/// with multiple/ Threads. In this test, we will demonstrate two things.
		/// First, we demonstrate how to set up different Threads by hand, which
		/// have different characteristics. The second thing we want to demonstrate
		/// is how "well-behaved" Threads can communicate with a controller through
		/// jointly accessable data items. We use the "ControlRegister" and
		/// "StatusRegister" fields in the CallerObject for this purpose. The
		/// test will employ processing on Main, since this must be turned on for
		/// the status and control feature to be demonstrated. 
		/// </summary>
		[Test(Description = "Level 2 series b tests for IRVTConcurrentCaller")]
		public void QATester_RunTest_IRVTConcurrentCaller_b()
		{
			// Made nice for article. Console.WriteLine("Running IRVTConcurrentCaller_b");
			Console.WriteLine("Running WorkerProcessControl");
			// Usual setup jazz.
			QATester_MultiProcessing_Testdata.ClearThreads();
			QATester_MultiProcessing_Testdata.ResetData();
			// Set the number of Threads locally - we need at least three Threads to demonstrate
			// everything we'd like. This is the number of Worker Threads.
			Int32 numSpawnedThreadsInUse = 3;
			// Build a new ThreadData array.
			IRVTThreadData<Int32>[] threadDataArray = new IRVTThreadData<Int32>[numSpawnedThreadsInUse+1];
			for(Int32 i = 0; i <= numSpawnedThreadsInUse; i++)
				threadDataArray[i] = new IRVTThreadData<Int32>();
			// Install our Main's CallerObject.
			threadDataArray[numSpawnedThreadsInUse].m_callerObject
				= m_IRVTCallerObjectAsInt32Replace_Main;
			// Install our long running Thread's CallerObject if we are not just processing
			// on Main. It could be anywhere, but we'll just make it first. 
			if(numSpawnedThreadsInUse > 0)
				threadDataArray[0].m_callerObject = m_IRVTCallerObjectAsInt32Replace_LongRunningThread;
			// Same deal for the slow running Thread.
			if(numSpawnedThreadsInUse > 1)
				threadDataArray[1].m_callerObject = m_IRVTCallerObjectAsInt32Replace_SlowRunningThread;
			// All of the rest of the Thread CallerObject's (if any) will be synthesized
			// internally by the TestRunner. We have three Worker Threads altogether, so
			// the TestRunner will be synthesizing just one.
			QATester_MultiProcessing_Testdata.IRVTTestRunner<Int32>(
				QATester_MultiProcessing_Testdata.IRVTDelayedConcurrentCallerProcess<Int32>,
					m_IRVTCallerObjectAsInt32Replace, threadDataArray,
						numSpawnedThreadsInUse, true);
		}
	}
	#endregion // Tests
	#region Helper Classes
	#region Thread Data Classes
	///////////////////////////////////////////////////////////////////////////
	// The classes in this region were constructed for use within the
	// demonstration system. These are used to hold information for each Thread
	// that is to be run in multithreading experiments contained herein. They
	// allow information to set up in arrays (the Thread object itself and it's
	// data) to be passed to the test running executives (the "TestRunners").
	///////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// This class holds a <see cref="System.Threading.Thread"/> reference and
	/// also the "CallerObject" for Threads processing Int32's.
	/// </summary>
	public class Int32ThreadData
	{
		/// <summary>
		/// The <see cref="System.Threading.Thread"/>.
		/// </summary>
		public Thread m_thread;
		/// <summary>
		/// The data for an Int32 CallerProcess.
		/// </summary>
		public Int32ConcurrentOpCallerObject m_callerObject;
	}
	/// <summary>
	/// This is the Generic version for RVT's.
	/// </summary>
	public class RVTTypeThreadData<T, UValueType>
		where T : class, IReferencedValueType<UValueType>
		where UValueType : struct
	{
		/// <summary>
		/// The <see cref="System.Threading.Thread"/>.
		/// </summary>
		public Thread m_thread;
		/// <summary>
		/// The data for a Generic RVT CallerProcess.
		/// </summary>
		public RVTTypeConcurrentOpCallerObject<T, UValueType> m_callerObject;
	}
	/// <summary>
	/// This is the Generic version for IRVT's.
	/// </summary>
	public class IRVTThreadData<UValueType>
		where UValueType : struct
	{
		/// <summary>
		/// The <see cref="System.Threading.Thread"/>.
		/// </summary>
		public Thread m_thread;
		/// <summary>
		/// The data for a Generic IRVT CallerProcess.
		/// </summary>
		public IRVTConcurrentOpCallerObject<UValueType> m_callerObject;
	}
	#endregion // Thread Data Classes
	#region CallerObjects
	///////////////////////////////////////////////////////////////////////////
	// The classes contained herein are containers for parameters and data for
	// for the various <see cref="System.Threading.ParameterizedThreadStart"/>
	// delegates that are used in multithreading tests. They are designed to be
	// populated with information parameters and then passed in to a Thread
	// upon startup. The method running on the Thread then picks off the
	// parameters for the test.
	///////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// This CallerObject is designed to support the simple non-Generic Int32
	/// tests. It is designed to support the simple <see cref="Int32ConcurrentOpCaller"/>
	/// delegate which invokes Int32 operations by calling an <see cref="Int32Op"/>
	/// delegate.
	/// </summary>
	public class Int32ConcurrentOpCallerObject
	{
		/// <summary>
		/// This is the Int32 - specific OP caller.
		/// </summary>
		public Int32ConcurrentOpCaller m_caller;
		/// <summary>
		/// This is the delegate that will perform operations on the passed
		/// Int32 when processing occurs.
		/// </summary>
		public Int32Op m_oP;
		/// <summary>
		/// This parameter is the number of iterations the internal Caller
		/// running on a Thread will perform in a given experiment.
		/// </summary>
		public Int32 m_numCallsOnThread;
		/// <summary>
		/// This is the generator for random Int32 data. 
		/// </summary>
		public IAuditingGenerator<Int32> m_numberGenerator;
		/// <summary>
		/// This is the generator for random delay data. Delays are always Int32's
		/// in all of our experiments.
		/// </summary>
		public IAuditingGenerator<Int32> m_delayGenerator;
		/// <summary>
		///	This is used to hold a copy of the common target that can be used to
		/// record its initial value at the initialization of an experiment.
		/// </summary>
		public Int32 m_target;

		/// <summary>
		/// Main constructor just sets everything.
		/// </summary>
		public Int32ConcurrentOpCallerObject(Int32ConcurrentOpCaller caller,
			Int32Op oP, Int32 numCallsOnThread, IAuditingGenerator<Int32> numberGenerator,
				IAuditingGenerator<Int32> delayGenerator, Int32 target)
		{
			m_caller = caller;
			m_oP = oP;
			m_numCallsOnThread = numCallsOnThread;
			m_numberGenerator = numberGenerator;
			m_delayGenerator = delayGenerator;
			m_target = target;
		}

		/// <summary>
		/// Copy constructor. Makes shallow copies of everything.
		/// </summary>
		public Int32ConcurrentOpCallerObject(Int32ConcurrentOpCallerObject callerObject)
		{
			m_caller = callerObject.m_caller;
			m_oP = callerObject.m_oP;
			m_numCallsOnThread = callerObject.m_numCallsOnThread;
			m_numberGenerator = callerObject.m_numberGenerator;
			m_delayGenerator = callerObject.m_delayGenerator;
			m_target = callerObject.m_target;
		}
		#region Methods
		/// <summary> Getter for the field. </summary>
		public object GetReferenceTarget()
		{ return m_target; }
		/// <summary>
		/// This method spawns a new CallerObject by copying the old over and
		/// spawning two new generators for it.
		/// </summary>
		/// <param name="initialState">
		/// This is the initial state that the new delay and number generators are
		/// initialized with.
		/// </param>
		/// <returns>
		/// The new CallerObject that has new independent generators with the
		/// same parameters as the generators on the current instance, but with
		/// different initial states.
		/// </returns>
		public Int32ConcurrentOpCallerObject SpawnCallerObject(Int32 initialState)
		{
			Int32ConcurrentOpCallerObject newObject
				= new Int32ConcurrentOpCallerObject(this);
			newObject.m_numberGenerator = newObject.m_numberGenerator.SpawnGenerator(initialState);
			newObject.m_delayGenerator = newObject.m_delayGenerator.SpawnGenerator(initialState);
			return newObject;
		}
		#endregion // Methods
		#region Properties
		//// These are all sort of redundant, since the fileds are public.
		/// <summary> Getter for the field. </summary>
		public Int32ConcurrentOpCaller Caller
		{ get { return m_caller; } }
		/// <summary> Getter for the field. </summary>
		public Int32Op Op
		{ get { return m_oP; } }
		/// <summary> Getter for the field. </summary>
		public Int32 NumCallsOnThread
		{ get { return m_numCallsOnThread; } }
		/// <summary> Getter for the field. </summary>
		public IAuditingGenerator<Int32> NumberGenerator
		{ get { return m_numberGenerator; } }
		/// <summary> Getter for the field. </summary>
		public IAuditingGenerator<Int32> DelayGenerator
		{ get { return m_delayGenerator; } }
		#endregion // Properties
	}
	/// <summary>
	/// This CallerObject is designed to support the full Generic RVT "Type" in
	/// the concurrency tests. It is designed to support the
	/// <see cref="RVTTypeConcurrentOpCaller&lt;T, UValueType&gt;"/> caller delegate
	/// which invokes T - valued operations by calling an <see cref="RVTOp&lt;T, UValueType&gt;"/>
	/// delegate.
	/// </summary>
	public class RVTTypeConcurrentOpCallerObject<T, UValueType>
		where T : class, IReferencedValueType<UValueType>
			where UValueType : struct
	{
		/// <summary>
		/// This is a caller that takes the full <see typeparamref="T"/>.
		/// </summary>
		public RVTTypeConcurrentOpCaller<T, UValueType> m_caller;
		/// <summary>
		/// This is the delegate that will perform operations on the passed
		/// RVT of type <see typeparamref="T"/> when processing occurs.
		/// </summary>
		public RVTOp<T, UValueType> m_rVToP;
		/// <summary> Same old. </summary>
		public Int32 m_numCallsOnThread;
		/// <summary> Defined as Int32 generator to demo ConvertNumber. </summary>
		public IAuditingGenerator<Int32> m_numberGenerator;
		/// <summary> Always use an Int32 generator for delays. </summary>
		public IAuditingGenerator<Int32> m_delayGenerator;
		/// <summary>
		/// This points to the target. Note <see typeparamref="T"/> is a class
		/// so this is a reference - it can be read/write.
		/// </summary>
		public T m_target;

		/// <summary>
		/// Main constructor just sets everything. The internal value of target is
		/// set to default(UValueType).
		/// </summary>
		public RVTTypeConcurrentOpCallerObject(RVTTypeConcurrentOpCaller<T, UValueType> caller,
			RVTOp<T, UValueType> rVToP, Int32 numCallsOnThread, IAuditingGenerator<Int32> numberGenerator,
				IAuditingGenerator<Int32> delayGenerator, T target)
		{
			m_caller = caller;
			m_rVToP = rVToP;
			m_numCallsOnThread = numCallsOnThread;
			m_numberGenerator = numberGenerator;
			m_delayGenerator = delayGenerator;
			// Point to the target.
			m_target = target;
			// Initialize it.
			((IReferencedValueType<UValueType>)m_target).Value = default(UValueType);
		}

		/// <summary>
		/// Copy constructor. Makes shallow copies of everything.
		/// </summary>
		public RVTTypeConcurrentOpCallerObject(RVTTypeConcurrentOpCallerObject<T, UValueType> callerObject)
		{
			m_caller = callerObject.m_caller;
			m_rVToP = callerObject.m_rVToP;
			m_numCallsOnThread = callerObject.m_numCallsOnThread;
			m_numberGenerator = callerObject.m_numberGenerator;
			m_delayGenerator = callerObject.m_delayGenerator;
			m_target = callerObject.m_target;
		}

		#region Methods
		/// <summary> Getter for the field. </summary>
		public T GetReferenceTarget()
		{ return m_target; }
		/// <summary>
		/// This method spawns a new CallerObject by copying the old over and
		/// spawning two new generators for it. The generators have the same
		/// parameters, but a different initial state.
		/// </summary>
		/// <param name="initialState">
		/// This is the initial state that the new delay and number generators are
		/// initialized with.
		/// </param>
		/// <returns>
		/// A copy of the old object with an independent copy of the generators.
		/// </returns>
		public RVTTypeConcurrentOpCallerObject<T, UValueType> SpawnCallerObject(Int32 initialState)
		{
			RVTTypeConcurrentOpCallerObject<T, UValueType> newObject
				= new RVTTypeConcurrentOpCallerObject<T, UValueType>(this);
			newObject.m_numberGenerator = newObject.m_numberGenerator.SpawnGenerator(initialState);
			newObject.m_delayGenerator = newObject.m_delayGenerator.SpawnGenerator(initialState);
			return newObject;
		}
		#endregion // Methods
		#region Properties
		//// Properties are again redundant, but it's good to show how to build
		//// Generic Properties.
		/// <summary>
		/// In this case the Property provides access to a Generic delegate. A delegate
		/// is no different than any other Type that is exposed through a Property.
		/// Neither is a Generic any different from any other delegate from this perspective.
		/// This Property also has a Set method. The Set method could be used to change
		/// the delegate at any time.
		/// </summary>
		public RVTTypeConcurrentOpCaller<T, UValueType> Caller
		{ get { return m_caller; } set { m_caller = value; } }
		/// <summary> Getter for the field. Same sort of comment for a Generic OP. </summary>
		public RVTOp<T, UValueType> Op
		{ get { return m_rVToP; }}
		/// <summary> Getter for the field. </summary>
		public Int32 NumCallsOnThread
		{ get { return m_numCallsOnThread; } }
		// Both generators are Int32.
		/// <summary> Getter for the field. </summary>
		public IAuditingGenerator<Int32> NumberGenerator
		{ get { return m_numberGenerator; } }
		/// <summary> Getter for the field. </summary>
		public IAuditingGenerator<Int32> DelayGenerator
		{ get { return m_delayGenerator; } }
		#endregion // Properties
	}
	/// <summary>
	/// This CallerObject is designed to support the Generic IRVT tests. In these
	/// tests, RVTs are handled only through their interface,
	/// <see cref="IReferencedValueType&lt;UValueType&gt;"/>.
	/// This CallerObject is designed to support the
	/// <see cref="IRVTConcurrentOpCaller&lt;UValueType&gt;"/> caller delegate
	/// which invokes UValueType - valued operations by calling an
	/// <see cref="IRVTOp&lt;UValueType&gt;"/> delegate. Like the delegate
	/// it supports, the RVT is handled through its interface only.
	/// </summary>
	/// <remarks>
	/// This class adds support for the "Thread control" demonstration by
	/// including a "StatusRegister" and a "ControlRegister" and some specialized
	/// Properties to access them.
	/// </remarks>
	public class IRVTConcurrentOpCallerObject<UValueType>
		where UValueType : struct
	{
		/// <summary>
		/// This is the delegate that will perform operations on the passed
		/// IRVT when processing occurs.
		/// </summary>
		public IRVTConcurrentOpCaller<UValueType> m_caller;
		/// <summary> The Generic IRVT OP. </summary>
		public IRVTOp<UValueType> m_iRVToP;
		/// <summary>
		/// See <see cref="RVTTypeConcurrentOpCallerObject&lt;T, UValueType&gt;"/>.
		/// </summary>
		public Int32 m_numCallsOnThread;
		/// <summary>
		/// Generator for the data - this time a Generic generator. 
		/// </summary>
		public IAuditingGenerator<UValueType> m_numberGenerator;
		/// <summary>
		/// Always use an Int32 generator for delays.
		/// </summary>
		public IAuditingGenerator<Int32> m_delayGenerator;
		/// <summary>
		/// This points to the target, whose access is to be synchronized. This
		/// time it's handled through the interface.
		/// </summary>
		public IReferencedValueType<UValueType> m_target;
		/// <summary>
		/// This is a simple example of a jointly accessible data item that can be used
		/// to signal a cooperating Thread process to stop. This data item is
		/// only written by the "control program" and is only read by the Worker
		/// Thread, so there is no need for synchronization. It needs to be "volatile",
		/// though, to make sure it is written out to core as soon as it written
		/// by a "control program".
		/// </summary>
		public volatile Int32 m_controlRegister;
		/// <summary>
		/// This is a status variable that is written by the Worker Thread
		/// and read by the control program. Again, this would not require
		/// synchronization, since it is only written by one participant.
		/// Should be volatile again, though.
		/// </summary>
		public volatile Int32 m_statusRegister;

		/// <summary>
		/// Main constructor just sets everything. The internal value of target is
		/// set to default(UValueType).
		/// </summary>
		public IRVTConcurrentOpCallerObject(IRVTConcurrentOpCaller<UValueType> caller,
			IRVTOp<UValueType> iRVToP, Int32 numCallsOnThread, IAuditingGenerator<UValueType> numberGenerator,
				IAuditingGenerator<Int32> delayGenerator, IReferencedValueType<UValueType> target)
		{
			m_caller = caller;
			m_iRVToP = iRVToP;
			m_numCallsOnThread = numCallsOnThread;
			m_numberGenerator = numberGenerator;
			m_delayGenerator = delayGenerator;
			// Point to the target.
			m_target = target;
			// Initialize it.
			m_target.Value = default(UValueType);
			// The ControlRegister and StatusRegister are examples of "one-way"
			// synchronization data items that are either read-only or write-only
			// for a participant (either the MultiProcess or the MultiProcessController)
			// in a given ConcurrencyTransaction. These are normally accessed through a
			// "split interface", where one interface has the "get" method and one
			// interface has the "set" method.
			m_controlRegister = 0;
			m_statusRegister = 0;
		}

		/// <summary>
		/// Copy constructor. Makes shallow copies of everything.
		/// </summary>
		public IRVTConcurrentOpCallerObject(IRVTConcurrentOpCallerObject<UValueType> callerObject)
		{
			m_caller = callerObject.m_caller;
			m_iRVToP = callerObject.m_iRVToP;
			m_numCallsOnThread = callerObject.m_numCallsOnThread;
			m_numberGenerator = callerObject.m_numberGenerator;
			m_delayGenerator = callerObject.m_delayGenerator;
			m_target = callerObject.m_target;
			m_controlRegister = callerObject.m_controlRegister;
			m_statusRegister = callerObject.m_statusRegister;
		}
		#region Methods
		/// <summary>
		/// This method spawns a new CallerObject by copying the old over and
		/// spawning two new generators for it. The generators have the same
		/// parameters, but a different initial state.
		/// </summary>
		/// <param name="initialState">
		/// This is the initial state that the new delay and number generators are
		/// initialized with.
		/// </param>
		/// <returns>
		/// A copy of the old object with an independent copy of the generators.
		/// </returns>
		public IRVTConcurrentOpCallerObject<UValueType> SpawnCallerObject(Int32 initialState)
		{
			IRVTConcurrentOpCallerObject<UValueType> newObject
				= new IRVTConcurrentOpCallerObject<UValueType>(this);
			newObject.m_numberGenerator = newObject.m_numberGenerator.SpawnGenerator(initialState);
			newObject.m_delayGenerator = newObject.m_delayGenerator.SpawnGenerator(initialState);
			return newObject;
		}
		#endregion // Methods
		#region Properties
		/// <summary> Getter for the field. </summary>
		public IRVTConcurrentOpCaller<UValueType> Caller
		{ get { return m_caller; } }
		/// <summary> Getter for the field. </summary>
		public IRVTOp<UValueType> Op
		{ get { return m_iRVToP; } }
		/// <summary> Getter for the field. </summary>
		public Int32 NumCallsOnThread
		{ get { return m_numCallsOnThread; } }
		/// <summary> Getter for the field. </summary>
		public IAuditingGenerator<UValueType> NumberGenerator
		{ get { return m_numberGenerator; } }
		/// <summary> Getter for the field. </summary>
		public IAuditingGenerator<Int32> DelayGenerator
		{ get { return m_delayGenerator; } }
		/// <summary> Getter for the field. </summary>
		public IReferencedValueType<UValueType> GetReferenceTarget()
		{ return m_target; }
		//// The following two are not redundant with the fields. They expose our
		//// ControlRegister and our StatusRegister in a special way. Well, the
		//// ThreadStopNow does, anyway. You get the picture......
		/// <summary>
		/// Reads the internal register and says to stop if it's positive. Designed
		/// to be read by a CallerProcess.
		/// </summary>
		public bool ThreadStopNow
		{ get { if(m_controlRegister > 0) return true; else return false; } }
		/// <summary>
		/// Reads the internal register and reports iteration number. Designed
		/// to be read by a MultiProcessController (in our examples this is the
		/// TestRunnner).
		/// </summary>
		public Int32 CurrentIteration
		{ get { return m_statusRegister;} }
		#endregion // Properties
	}
	#endregion // CallerObjects

	#region Number Generators
	/// <summary>
	/// This interface defines a class of number generators that provide stimulus
	/// for testing of MultiProcess contention. It provides the ability to create
	/// a new generator and get numbers from it. It also provides the ability
	/// to spawn a "subgenerator" with an initial state that can be derived from
	/// a Thread's ID or some other source. Generators can be of a statistical or
	/// deterministic nature. The generator is assumed to produce Int32 numbers
	/// internally, which are mapped to other numbers of type <see typeparamref="T"/>
	/// for output.
	/// </summary>
	/// <typeparam name="T">
	/// This is the Type of the number to be generated,
	/// </typeparam>
	public interface IAuditingGenerator<T>
	{
		/// <summary>
		/// Converts the internal number to an arbitrary Type. This Type is dynamically
		/// determined on each call and is not necessarily equal to <see typeparamref="T"/>.
		/// If the Type is a <see cref="System.ValueType"/>, it places it in a box.
		/// </summary>
		/// <returns>
		/// A ReferenceType or boxed version of a ValueType. This will be <c>null</c>
		/// if the conversion cannot be accomplished.
		/// </returns>
		System.Object ConvertNumber(Type outputType);
		/// <summary>
		/// Gets the generator's history of generated numbers.
		/// </summary>
		/// <returns>
		/// The Int32-valued list. May be <c>null</c> if auditing not enabled.
		/// </returns>
		List<Int32> GetNumberHistory();
		/// <summary>
		/// Gets the generator's history of generated operations by the OP delegate.
		/// </summary>
		/// <returns>
		/// The T-valued list. May be <c>null</c> if auditing not enabled.
		/// </returns>
		List<T> GetOperationHistory();
		/// <summary>
		/// This method makes a copy of an existing generator and sets its initial
		/// state to a specified value, but otherwise initializes the generator to
		/// the initial values specified at construction time for the original
		/// generator, not the CURRENT state of the original generator. This includes
		/// clearing histories (if on) and resetting the operation state.
		/// </summary>
		/// <param name="initialState">
		/// This is the specified initial state that the new generator should take.
		/// This is usually an initial value for a random generator or an initial
		/// value for a counter, etc.
		/// </param>
		/// <returns>
		/// The new <see cref="IAuditingGenerator&lt;T&gt;"/> with the prescribed
		/// state.
		/// </returns>
		IAuditingGenerator<T> SpawnGenerator(Int32 initialState);
		/// <summary>
		/// This gets the next number in sequence from the generator.
		/// </summary>
		/// <returns>
		/// The T-valued number.
		/// </returns>
		T Next();
		/// <summary>
		/// Resets the generator to it's original state.
		/// </summary>
		void Reset();
		/// <summary>
		/// Resets the generator to a specified state.
		/// </summary>
		/// <param name="initialState">
		/// The specified Int32-valued state to reset the generator to.
		/// </param>
		void Reset(Int32 initialState);
	}

	/// <summary>
	/// A generator for Int32 random #s. The class is designed to keep
	/// track of the result of operations that are taking place across multiple
	/// locked Threads and compare the results using various synchronization
	/// schemes with the "true" results. Closed Int32 implementation of the
	/// Generic interface <see cref="IAuditingGenerator&lt;T&gt;"/>.
	/// </summary>
	public class AuditingInt32RNGenerator : AuditingRandomGenerator, IAuditingGenerator<Int32>
	{
		#region Class Fields
		// The initial value of the "state" of the Int32 operation. This is the
		// state that is reset with "reset".
		Int32 m_initialOpState;
		// The "state" of the Int32 operation.
		Int32 m_opState;
		// The delegate that defines the Int32 operation. Default is not to
		// operate an internal delegate.
		Int32Op m_opDelegate = null;
		// List of Op history.
		List<Int32> m_opHistory;
		#endregion // Class Fields
		#region Constructors
		/// <summary>
		/// Default constructor for inheritance support.
		/// </summary>
		public AuditingInt32RNGenerator() { }
		/// <summary>
		/// Main constructor sets up the Int32 internal generator and the Int32
		/// OP-related items.
		/// </summary>
		/// <param name="seed">
		/// Initial seed defining the "state" of the generator.
		/// </param>
		/// <param name="minValue">
		/// Minimum (inclusive) value that Int32 numbers will take on.
		/// </param>
		/// <param name="maxValue">
		/// Maximum (inclusive) value that Int32 numbers will take on.
		/// </param>
		/// <param name="oP">
		/// The OP delegate to be used inside the generator.
		/// </param>
		/// <param name="initialOpState">
		/// The initial state of the OP output.
		/// </param>
		/// <param name="historyOn">
		/// <c>true</c> if the random number history and the OP history are to
		/// be captured into the internal lists.
		/// </param>
		public AuditingInt32RNGenerator(Int32 seed, Int32 minValue, Int32 maxValue,
			Int32Op oP, Int32 initialOpState, System.Boolean historyOn)
			: base(seed, minValue, maxValue, historyOn)
		{
			// Add our Int32 - specific stuff.
			m_opDelegate = oP;
			m_initialOpState = initialOpState;
			if(m_historyOn) {
				m_opHistory = new List<Int32>();
			}
		}
		/// <summary>
		/// Copy constructor. Makes a copy of the generator and initializes it to
		/// it's initial state according to the original inititial state of the
		/// original generator, not the CURRENT state of the original generator.
		/// It also clears the lists (if any) and sets the oPstate to it's initial
		/// value.
		/// </summary>
		/// <param name="generator">
		/// The existing generator to make a copy of.
		/// </param>
		public AuditingInt32RNGenerator(AuditingInt32RNGenerator generator)
			: base(generator)
		{
			// Copy the Int32 - specific stuff.
			m_opDelegate = generator.m_opDelegate;
			m_initialOpState = generator.m_initialOpState;
			m_historyOn = generator.m_historyOn;
			if(m_historyOn) {
				m_opHistory = new List<Int32>();
			}
		}
		#endregion // Constructors
		#region Methods
		/// <summary>
		/// Gets the operation history.
		/// </summary>
		/// <returns>
		/// A <See cref="System.Collections.Generic.List&lt;Int32&gt;"/> if history
		/// was turned on in the constructor, otherwise <c>null</c>.
		/// </returns>
		public List<Int32> GetOperationHistory()
		{
			return m_opHistory;
		}
		/// <summary>
		/// Gets the next integer from the internal RNG and accumulates it through
		/// the OP.
		/// </summary>
		/// <returns>
		/// The <see cref="System.Int32"/> value produced by the random number
		/// generator.
		/// </returns>
		/// <remarks>
		/// If we were completely and absolutely fastidious about not duplicating
		/// code anywhere, we'd break up this method into a base part in
		/// <see cref="AuditingRandomGenerator"/> and a Type - specific part here.
		/// But we're not........
		/// </remarks>
		public virtual Int32 Next()
		{
			// .Net's generator is exclusive on the high end (+1).
			Int32 rn = m_rng.Next(m_minValue, m_maxValue + 1);
			m_lastInt32Num = rn;
			// If we have a delegate, this particular generator accumulates into
			// its Opstate.
			if(m_opDelegate != null)
				m_opState = m_opDelegate(ref m_opState, rn);
			// Store variables in the history if history is on.
			if(m_historyOn) {
				m_numHistory.Add(rn);
				m_opHistory.Add(m_opState);
			}
			return rn;
		}
		/// <summary>
		/// Creates a new copy of the generator with a given initial state.
		/// </summary>
		/// <returns>
		/// An <see cref="IAuditingGenerator&lt;Int32&gt;"/> with the same parameters
		/// as the parent generator (this), but a different internal state.
		/// </returns>
		public IAuditingGenerator<Int32> SpawnGenerator(Int32 initialState)
		{
			IAuditingGenerator<Int32> generator = new AuditingInt32RNGenerator(this);
			generator.Reset(initialState);
			return generator;
		}
		/// <summary>
		/// Resets the generator and the states of everything and flushes history
		/// lists if they are in use. We need an override to reset OP's etc.
		/// </summary>
		public override void Reset()
		{
			// Call base to do most things.
			base.Reset();
			// Add on our Int32 - specific things.
			m_opState = m_initialOpState;
			if(m_historyOn) {
				m_opHistory.Clear();
			}
		}
		#endregion // Methods
	}
	/// <summary>
	/// A generator for random #s. The class is designed to keep
	/// track of the result of operations that are taking place across multiple
	/// locked Threads and compare the results using various synchronization
	/// schemes with the "true" results. Open Generic implementation of the
	/// Generic interface <see cref="IAuditingGenerator&lt;T&gt;"/>.
	/// </summary>
	public class AuditingRNGenerator<T> : AuditingRandomGenerator, IAuditingGenerator<T>
	{
		#region Class Fields
		// The initial value of the "state" of the Int32 operation. This is the
		// state that is reset with "reset".
		T m_initialOpState;
		// The "state" of the Type T operation.
		T m_opState;
		// The delegate that defines the Generic "OP". Default is not to
		// operate an internal delegate (null).
		Op<T> m_opDelegate = null;
		// List of OP history.
		List<T> m_opHistory;

		///////////////////////////////////////////////////////////////////////
		// A little extra bookeeping we like/need to do for a Generic
		// generator.
		///////////////////////////////////////////////////////////////////////
		// Hold on to our Type.
		Type m_typeType = typeof(T);
		// The last number that was generated and then converted. We need this
		// field to be able to hold the number for conversion out the "back door",
		// using ConvertNumber(), among other reasons.
		T m_lastNum;

		#endregion // Class Fields
		#region Constructors
		/// <summary>
		/// Default constructor for inheritance support.
		/// </summary>
		public AuditingRNGenerator(){}
		/// <summary>
		/// Main constructor sets up the Int32 internal generator and the Type T
		/// oP-related items.
		/// </summary>
		/// <param name="seed">
		/// Initial seed defining the "state" of the generator.
		/// </param>
		/// <param name="minValue">
		/// Minimum (inclusive) value that Int32 numbers will take on.
		/// </param>
		/// <param name="maxValue">
		/// Maximum (inclusive) value that Int32 numbers will take on.
		/// </param>
		/// <param name="oP">
		/// The OP delegate to be used inside the generator.
		/// </param>
		/// <param name="initialOpState">
		/// The initial state of the OP output.
		/// </param>
		/// <param name="historyOn">
		/// <c>true</c> if the random number history and the OP history are to
		/// be captured into the internal lists.
		/// </param>
		/// <remarks>
		/// This constructor calls the bases to do most of the work.
		/// </remarks>
		public AuditingRNGenerator(Int32 seed, Int32 minValue, Int32 maxValue,
			Op<T> oP, T initialOpState, System.Boolean historyOn)
				: base(seed, minValue, maxValue, historyOn)

		{
			// Do the Type T specific stuff.
			m_opDelegate = oP;
			m_initialOpState = initialOpState;
			if(m_historyOn) {
				m_opHistory = new List<T>();
			}
		}
		/// <summary>
		/// Copy constructor. Makes a copy of the generator and initializes it to
		/// it's initial state according to the original inititial state of the
		/// original generator, not the CURRENT state of the original generator.
		/// It also clears the lists (if any) and sets the oPstate to it's initial
		/// value.
		/// </summary>
		/// <param name="generator">
		/// The existing generator to make a copy of.
		/// </param>
		public AuditingRNGenerator(AuditingRNGenerator<T> generator)
			: base(generator)
		{
			// Copy the Type T - specific stuff.
			m_opDelegate = generator.m_opDelegate;
			m_initialOpState = generator.m_initialOpState;
			if(m_historyOn) {
				m_opHistory = new List<T>();
			}
		}
		#endregion // Constructors
		#region Methods
		/// <summary>
		/// Gets the operation history.
		/// </summary>
		/// <returns>
		/// A <See cref="System.Collections.Generic.List&lt;Int32&gt;"/> if history
		/// was turned on in the constructor, otherwise <c>null</c>.
		/// </returns>
		public List<T> GetOperationHistory()
		{
			return m_opHistory;
		}
		/// <summary>
		/// Gets the next integer from the internal RNG and accumulates it through
		/// the OP.
		/// </summary>
		/// <returns>
		/// The <see cref="System.Int32"/> value produced by the random number
		/// generator.
		/// </returns>
		public virtual T Next()
		{
			// .Net's generator is exclusive on the high end (+1).
			Int32 rn = m_rng.Next(m_minValue, m_maxValue + 1);
			m_lastInt32Num = rn;
			m_lastNum = ConvertToT(rn);
			// If we have a delegate, this particular generator accumulates into
			// its Opstate.
			if(m_opDelegate != null)
				m_opState = m_opDelegate(ref m_opState, m_lastNum);
			// Store variables in the history if history is on.
			if(m_historyOn) {
				m_numHistory.Add(rn);
				m_opHistory.Add(m_opState);
			}
			return m_lastNum;
		}
		/// <summary>
		/// Creates a new copy of the generator with a given initial state.
		/// </summary>
		/// <returns>
		/// An <see cref="IAuditingGenerator&lt;T&gt;"/> with the same parameters
		/// as the parent generator (this), but a different internal state.
		/// </returns>
		public IAuditingGenerator<T> SpawnGenerator(Int32 initialState)
		{
			IAuditingGenerator<T> generator = new AuditingRNGenerator<T>(this);
			generator.Reset(initialState);
			return generator;
		}
		/// <summary>
		/// Resets the generator and the states of everything and flushes history
		/// lists if they are in use. We need an override to reset OP's etc.
		/// </summary>
		public override void Reset()
		{
			// Call base to do most things.
			base.Reset();
			// Add on our Type T - specific things.
			m_opState = m_initialOpState;
			if(m_historyOn) {
				m_opHistory.Clear();
			}
		}
		/// <summary>
		/// Convert's the .Net's generator output (Int32's) into whatever the
		/// Type T is.
		/// </summary>
		/// <returns>
		/// The converted <see cref="System.Int32"/> value.
		/// </returns>
		/// <Exceptions>
		/// <Exception>
		/// An <see cref="ApplicationException"/> is generated with the message
		/// "Can't convert random # to T in AuditingGenerator&lt;T&gt;" if the
		/// conversion fails.
		/// </Exception>
		/// </Exceptions>
		/// <remarks>
		/// <para>
		/// This simple method just calls <see cref="AuditingRandomGenerator.ConvertToAny"/>
		/// interface method to do a conversion to another .Net Type. Override this
		/// method if you need something more.
		/// </para>
		/// <para>
		/// Note that this method is not specified in <see cref="IAuditingGenerator&lt;T&gt;"/>.
		/// This is an example of a method that could support an inheriting Type that
		/// wished to employ this additional functionality. This could be an Interface
		/// inheriting from <see cref="IAuditingGenerator&lt;T&gt;"/>, a completely
		/// different Interface or a class deriving from this class.
		/// </para>
		/// </remarks>
		protected virtual T ConvertToT(Int32 int32Rn)
		{
			try {
				// Do it with a regular conversion.
				return (T)(ConvertToAny(int32Rn, m_typeType));
			}
			catch {
				Type typeType = typeof(T);
				// We can't really do much if we can't convert to T.
				throw new ApplicationException("Can't convert random # to \"T\" ("
					+ typeType.ToString() + ") in AuditingGenerator<T>");
			}
		}
		#endregion // Methods
	}
	/// <summary>
	/// A generator base class for generating random #s. The class is designed
	/// to keep track of the result of operations that are taking place across
	/// multiple locked Threads and compare the results using various synchronization
	/// schemes with the "true" results. This class implements the common internal
	/// bookeeping operations needed for any random generator which has a copy
	/// of <see cref="System.Random"/> inside.
	/// </summary>
	public abstract class AuditingRandomGenerator
	{
		#region Class Fields
		/// <summary>
		/// For first time warning about conversions. A conversion failure in
		/// ConvertNumber() does not generate an exception in this base class.
		/// The first time a conversion failure occurs, however, we announce it
		/// at the Console.
		/// </summary>
		protected bool m_firstTimeWarning = true;
		/// <summary>
		/// Seed from constructor.
		/// </summary>
		protected Int32 m_seed;
		/// <summary>
		/// The last number that was generated.
		/// </summary>
		protected Int32 m_lastInt32Num;
		/// <summary>
		/// The minimum value of the integer to deliver (inclusive)
		/// </summary>
		protected Int32 m_minValue;
		/// <summary>
		/// The maximum value of the integer to deliver (inclusive) 
		/// </summary>
		protected Int32 m_maxValue;
		/// <summary>
		/// Contained .Net generator.
		/// </summary>
		protected Random m_rng;
		/// <summary>
		/// Tells if we are accumulating histories of the generator output and
		/// the OP result output. 
		/// </summary>
		protected System.Boolean m_historyOn;
		/// <summary>
		/// List of past RN's.
		/// </summary>
		protected List<Int32> m_numHistory;
		#endregion // Class Fields
		#region Constructors
		/// <summary>
		/// Default constructor for inheritance support.
		/// </summary>
		public AuditingRandomGenerator() { }
		/// <summary>
		/// Main constructor sets up the Int32 internal generator.
		/// </summary>
		/// <param name="seed">
		/// Initial seed defining the "state" of the generator.
		/// </param>
		/// <param name="minValue">
		/// Minimum (inclusive) value that Int32 numbers will take on.
		/// </param>
		/// <param name="maxValue">
		/// Maximum (inclusive) value that Int32 numbers will take on.
		/// </param>
		/// <param name="historyOn">
		/// <c>true</c> if the random number history is to be captured into the
		/// internal list.
		/// </param>
		public AuditingRandomGenerator(Int32 seed, Int32 minValue, Int32 maxValue,
			System.Boolean historyOn)
			: this()
		{
			m_seed = seed;
			m_lastInt32Num = seed;
			m_minValue = minValue;
			m_maxValue = maxValue;
			m_rng = new Random(m_seed);
			m_historyOn = historyOn;
			if(m_historyOn) {
				m_numHistory = new List<Int32>();
			}
		}
		/// <summary>
		/// Copy constructor. Makes a copy of the generator and initializes it to
		/// it's initial state according to the original inititial state of the
		/// original generator, not the CURRENT state of the original generator.
		/// It also clears the list (if set).
		/// </summary>
		/// <param name="generator">
		/// The existing generator to make a copy of.
		/// </param>
		public AuditingRandomGenerator(AuditingRandomGenerator generator)
			: this()
		{
			m_seed = generator.m_seed;
			m_lastInt32Num = generator.m_lastInt32Num;
			m_minValue = generator.m_minValue;
			m_maxValue = generator.m_maxValue;
			m_rng = new Random(m_seed);
			m_historyOn = generator.m_historyOn;
			if(m_historyOn) {
				m_numHistory = new List<Int32>();
			}
		}
		#endregion // Constructors
		#region Methods
		/// <summary>
		/// Gets a converted and boxed version of the last random number the
		/// generator produced.
		/// </summary>
		/// <param name="outputType">
		/// This is the Type that the Int32 number has to be converted to. It can
		/// be a reference (class) or ValueType (primitive Type or custom struct).
		/// Value Types are boxed.
		/// </param>
		/// <returns>
		/// A reference to a box containing a class or ValueType. Note that this
		/// reference must be <see cref="System.Object"/> and not not specialized
		/// to <see cref="System.ValueType"/>, since we may wish to convert to
		/// a C# class, not a boxed C# struct.
		/// </returns>
		public virtual System.Object ConvertNumber(Type outputType)
		{
			// Reference to what we've produced.
			System.Object convertedNumber = null;

			// We'll try this only if we know we might succeed. Problem is that T
			// could be anything - we don't want to be Type and platform-specific
			// by using our knowledge of what specific Types can be converted
			// a-priori.
			if(m_firstTimeWarning) {
				// Do it with a regular conversion.
				if((convertedNumber = ConvertToAny(m_lastInt32Num, outputType)) == null) {
					// Give warning, but only first time through - we might only care about
					// delays and collisions and we don't want to scroll to the screen.
					// (Conversions are usually only used for data).
					if(m_firstTimeWarning) {
						Console.WriteLine("Can't convert random # to" +
							outputType.ToString() + "in AuditingGenerator<T>");
						m_firstTimeWarning = false;
					}
				}
			}
			return convertedNumber;
		}
		/// <summary>
		/// Gets the random number generator history.
		/// </summary>
		/// <returns>
		/// A <See cref="System.Collections.Generic.List&lt;Int32&gt;"/> if history
		/// was turned on in the constructor, otherwise <c>null</c>.
		/// </returns>
		public List<Int32> GetNumberHistory()
		{
			return m_numHistory;
		}
		/// <summary>
		/// Resets the generator and the states of everything and flushes history
		/// lists if they are in use.
		/// </summary>
		public virtual void Reset()
		{
			m_rng = new Random(m_seed);
			m_lastInt32Num = m_seed;
			if(m_historyOn) {
				m_numHistory.Clear();
			}
		}
		/// <summary>
		/// Resets the generator and the states of everything and flushes history
		/// lists if they are in use. This version uses a parameter to initialize
		/// the internal state of the generator.
		/// </summary>
		/// <param name="initialState">
		/// This is a number that will set the internal initial state or "seed"
		/// of the generator.
		/// </param>
		public virtual void Reset(Int32 initialState)
		{
			// Change the seed and call reset.
			m_seed = initialState;
			Reset();
		}
		/// <summary>
		/// Convert's the .Net's generator output (Int32's) into any Type at all.
		/// The Type is examined dynamically and can change from call to call.
		/// This method will box primitive Types (anything the CLR's conversion
		/// of Int32 will support) that are produced. The client should override
		/// this method to convert to other Types of interest.
		/// </summary>
		/// <param name="int32Rn">
		/// The integer number to be converted.
		/// </param>
		/// <param name="outputType">
		/// The <see cref="System.Type"/> of the class or BOXed output struct
		/// or primitive Type.
		/// </param>
		/// <returns>
		/// The converted <see cref="System.Int32"/> value. A <c>null</c> value
		/// is returned if the conversion cannot be accomplished.
		/// </returns>
		/// <remarks>
		/// This simple method just uses Int32's IConvertible interface. Users
		/// needing to convert to something more exotic need to override this.
		/// </remarks>
		protected static System.Object ConvertToAny(Int32 int32Rn, Type outputType)
		{
			// Don't convert if we don't need to.
			if(outputType == typeof(Int32)) return int32Rn;
			// Do it with a regular conversion.
			try {
				return ((IConvertible)int32Rn).ToType(outputType, null);
			}
			catch {
			}
			return null;
		}
		#endregion // Methods
	}
	#endregion // Random Number Generators
	#endregion // Helper Classes
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
Kurt R. Matis received the B.S degree in Applied Mathemetics from Empire State College in 1981 and the PhD. degree in Electrical Engineering from Rensselaer Polytechnic Institute in 1984. He has been involved in several companies over the past 30 years, but has been most recently involved with the Macher-Plander Software Engineering Consortium, of which he is a co-founder. The Consortium is involved with education in .Net technologies and Software Quality Management topics.

Dr. Matis is a member of IEEE and the American Historical Truck Society. Kurt lives happily in Troy, NY with his beautiful wife, two beautiful daughters and his beautiful trucks.

Dr. Matis is interested in working with companies who wish assistance in porting legacy applications of all types to .Net. He can be reached at krogerma@aol.com.




Comments and Discussions