public async Task DoNotEnslaveAndDelayMessangerTest()
        {
            //The main difference, here as it should be used, but did not exist till .Net 4.5
            TaskCompletionSource <object> tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            ISequencerUC sequencer =
                SequencerUC
                .Construct()
                .Register(TCS.ReceiverInitialize, new StrategyOneOnOneUC())
                .Register(TCS.ReceiverRecord, new StrategyOneOnOneUC())
                .Register(TCS.MessangerSetResult, new StrategyOneOnOneUC())
            ;

            sequencer.Run(seq => Receiver(seq, tcs));                        //run Receiver in own thread
            await sequencer.TestPointAsync(TCS.ReceiverInitialize);          //receiver was running and is awaiting tcs now

            sequencer.Run(seq => Messanger(seq, tcs));                       //run Messanger in own thread
            await sequencer.TestPointAsync(TCS.MessangerSetResult);          //messanger SetResult executed

            var worker = await sequencer.TestPointAsync(TCS.ReceiverRecord); //get info about Receivers thread

            //Messanger was not executing code inside Receiver synchronously!
            Assert.AreNotEqual(worker.ProductionArg, nameof(Messanger));

            await sequencer.WhenAll();            // wait for all tasks to complete

            Assert.DoesNotThrow(() => sequencer.TryReThrowException());
        }
        public async Task AwaitAlreadyEnqueuedDataTest()
        {
            ISequencerUC sequencer =
                SequencerUC
                .Construct()
                .Register(AwaitAlreadyEnqueuedDataEnum.Enqueue2ItemsBegin, new StrategyOneOnOneUC())
                .Register(AwaitAlreadyEnqueuedDataEnum.Enqueue2ItemsEnd, new StrategyOneOnOneUC())
                .Register(AwaitAlreadyEnqueuedDataEnum.EnqueuedItemsAsyncBegin, new StrategyOneOnOneUC())
                .Register(AwaitAlreadyEnqueuedDataEnum.EnqueuedItemsAsyncEnd, new StrategyOneOnOneUC())
            ;

            const int throttle = 3;

            IConcurrentQueueNotifier <string> notifier = new ConcurrentQueueNotifier <string>(throttle);

            sequencer.Run(() => Insert2Items(sequencer, notifier));
            sequencer.Run(() => AwaitEnqueuedData(sequencer, notifier));

            await sequencer.TestPointCompleteAsync(AwaitAlreadyEnqueuedDataEnum.Enqueue2ItemsBegin);          //enqueue data

            await sequencer.TestPointCompleteAsync(AwaitAlreadyEnqueuedDataEnum.Enqueue2ItemsEnd);            //enqueue completed

            Assert.AreEqual(2, notifier.Count());

            await sequencer.TestPointCompleteAsync(AwaitAlreadyEnqueuedDataEnum.EnqueuedItemsAsyncBegin);          //begin awaiting enqueued data

            await sequencer.TestPointCompleteAsync(AwaitAlreadyEnqueuedDataEnum.EnqueuedItemsAsyncEnd);            //enqueued data should be detected

            await sequencer.WhenAll();

            sequencer.TryReThrowException();
        }
        public async Task Insert3ItemsThrottleTest()
        {
            ISequencerUC sequencer =
                SequencerUC
                .Construct()
                .Register(Insert3ItemsThrottleTestEnum.Enqueue3Items_Begin, new StrategyOneOnOneUC())
                .Register(Insert3ItemsThrottleTestEnum.Enqueue3Items_A, new StrategyOneOnOneUC())
                .Register(Insert3ItemsThrottleTestEnum.Enqueue3Items_B, new StrategyOneOnOneUC())
                .Register(Insert3ItemsThrottleTestEnum.Enqueue3Items_C_Throttle, new StrategyOneOnOneUC())
                .Register(Insert3ItemsThrottleTestEnum.Enqueue3Items_End, new StrategyOneOnOneUC())
                .Register(Insert3ItemsThrottleTestEnum.EnqueuedItemsAsyncBegin, new StrategyOneOnOneUC())
                .Register(Insert3ItemsThrottleTestEnum.EnqueuedItemsAsyncDataItem, new StrategyOneOnOneUC())
                .Register(Insert3ItemsThrottleTestEnum.EnqueuedItemsAsyncEnd, new StrategyOneOnOneUC())
            ;

            const int throttle = 3;

            IConcurrentQueueNotifier <string> notifier = new ConcurrentQueueNotifier <string>(throttle);

            sequencer.Run(() => Insert3ItemsThrottle(sequencer, notifier));
            sequencer.Run(() => AwaitDequeue3(sequencer, notifier));

            IProductionPointUC prodPoint;


            await sequencer.TestPointCompleteAsync(Insert3ItemsThrottleTestEnum.Enqueue3Items_Begin);

            await sequencer.TestPointCompleteAsync(Insert3ItemsThrottleTestEnum.Enqueue3Items_A);

            await sequencer.TestPointCompleteAsync(Insert3ItemsThrottleTestEnum.Enqueue3Items_B);

            prodPoint = await sequencer.TestPointCompleteAsync(Insert3ItemsThrottleTestEnum.Enqueue3Items_C_Throttle);

            Assert.IsFalse((prodPoint?.ProductionArg as Task)?.IsCompleted);
            Assert.AreEqual(3, notifier.Count());

            await sequencer.TestPointCompleteAsync(Insert3ItemsThrottleTestEnum.EnqueuedItemsAsyncBegin);

            prodPoint = await sequencer.TestPointCompleteAsync(Insert3ItemsThrottleTestEnum.EnqueuedItemsAsyncDataItem);

            Assert.AreEqual("A", prodPoint?.ProductionArg as string);

            //throttling should be deactivated, resuming
            await sequencer.TestPointCompleteAsync(Insert3ItemsThrottleTestEnum.Enqueue3Items_End);

            prodPoint = await sequencer.TestPointCompleteAsync(Insert3ItemsThrottleTestEnum.EnqueuedItemsAsyncDataItem);

            Assert.AreEqual("B", prodPoint?.ProductionArg as string);

            prodPoint = await sequencer.TestPointCompleteAsync(Insert3ItemsThrottleTestEnum.EnqueuedItemsAsyncDataItem);

            Assert.AreEqual("C", prodPoint?.ProductionArg as string);

            await sequencer.TestPointCompleteAsync(Insert3ItemsThrottleTestEnum.EnqueuedItemsAsyncEnd);

            await sequencer.WhenAll();

            sequencer.TryReThrowException();
        }
        public async Task MultipleUnRegistrationsTest()
        {
            var tickGenerator = new TickGenerator(10);

            ISequencerUC sequencer =
                SequencerUC
                .Construct()
                .Register(Steps.Notify, new StrategyOneOnOneUC())
            ;

            Action action = () =>
            {
                sequencer.Point(SeqPointTypeUC.Notify, Steps.Notify);
            };

            Task t = await tickGenerator.RegisterAsync(action).WrapIntoTask();

            Assert.IsTrue(t.IsCompleted);
            Assert.IsFalse(t.IsCanceled);
            Assert.IsFalse(t.IsFaulted);

            for (int i = 0; i < 10; i++)
            {
                await sequencer.TestPointAsync(Steps.Notify);
            }

            t = await tickGenerator.UnRegisterAsync(action).WrapIntoTask();

            Assert.IsTrue(t.IsCompleted);
            Assert.IsFalse(t.IsCanceled);
            Assert.IsFalse(t.IsFaulted);

            t = await tickGenerator.UnRegisterAsync(action).WrapIntoTask();

            Assert.IsTrue(t.IsCompleted);
            Assert.IsFalse(t.IsCanceled);
            Assert.IsFalse(t.IsFaulted);

            await sequencer.WhenAll();

            sequencer.TryReThrowException();
        }
Beispiel #5
0
        public async Task AwaitAheadOfDataTest()
        {
            ISequencerUC sequencer =
                SequencerUC
                .Construct()
                .Register(AwaitAheadOfDataEnum.Enqueue2ItemsBegin, new StrategyOneOnOneUC())
                .Register(AwaitAheadOfDataEnum.Enqueue2ItemsA, new StrategyOneOnOneUC())
                .Register(AwaitAheadOfDataEnum.Enqueue2ItemsEnd, new StrategyOneOnOneUC())
                .Register(AwaitAheadOfDataEnum.EnqueuedItemsAsyncBegin, new StrategyOneOnOneUC())
                .Register(AwaitAheadOfDataEnum.EnqueuedItemsAsyncAwaiting, new StrategyOneOnOneUC())
                .Register(AwaitAheadOfDataEnum.EnqueuedItemsAsyncEnd, new StrategyOneOnOneUC())
            ;

            const int throttle = 3;

            IConcurrentQueueNotifier <string> notifier = new ConcurrentQueueNotifier <string>(throttle);

            sequencer.Run(() => Enque2Items(sequencer, notifier));
            sequencer.Run(() => AwaitAhedOfData(sequencer, notifier));

            await sequencer.TestPointCompleteAsync(AwaitAheadOfDataEnum.EnqueuedItemsAsyncBegin);

            IProductionPointUC point = await sequencer.TestPointCompleteAsync(AwaitAheadOfDataEnum.EnqueuedItemsAsyncAwaiting);

            Task t = point.ProductionArg as Task;

            Assert.IsFalse(t?.IsCompleted);

            await sequencer.TestPointCompleteAsync(AwaitAheadOfDataEnum.Enqueue2ItemsBegin);

            await sequencer.TestPointCompleteAsync(AwaitAheadOfDataEnum.Enqueue2ItemsA);

            await sequencer.TestPointCompleteAsync(AwaitAheadOfDataEnum.EnqueuedItemsAsyncEnd);

            await sequencer.TestPointCompleteAsync(AwaitAheadOfDataEnum.Enqueue2ItemsEnd);

            Assert.AreEqual(1, notifier.Count());

            await sequencer.WhenAll();

            sequencer.TryReThrowException();
        }
        public async Task EnslaveAndDelayMessangerTest()
        {
            //The danger is hidden in using the messangers thread to run continuation,
            //for semaphores in messanger/receiver blocks it can easily create deadlock,

            //For monitor lock in messanger/receiver blocks it should mostly work well,
            // recursivness takes care of it.

            //For UI it is highly dangerous and unpredictable!
            //If messanger is executed from UI, it will most often execute continuation synchronously on UI.
            //BUT!
            //In certain cases TaskCompletionSource can decide to run continuation asynchronously on UI.
            //Same as if a delegate would not be executed directly but through BeginInvoke scheduled to queue
            //and executed later.
            //It is a breaking change to subsequent code, that might expect something will be already done before
            //subsequent code is executed.
            TaskCompletionSource <object> tcs = new TaskCompletionSource <object>();

            ISequencerUC sequencer =
                SequencerUC
                .Construct()
                .Register(TCS.ReceiverInitialize, new StrategyOneOnOneUC())
                .Register(TCS.ReceiverRecord, new StrategyOneOnOneUC())
                .Register(TCS.MessangerSetResult, new StrategyOneOnOneUC())
            ;

            sequencer.Run(seq => Receiver(seq, tcs));                        //run Receiver in its own thread
            await sequencer.TestPointAsync(TCS.ReceiverInitialize);          //receiver was running and is now awaiting tcs.Task

            sequencer.Run(seq => Messanger(seq, tcs));                       //run Messanger in its own thread
            await sequencer.TestPointAsync(TCS.MessangerSetResult);          //messanger SetResult executed

            var worker = await sequencer.TestPointAsync(TCS.ReceiverRecord); //receiver was running and is now awaiting tcs.Task

            //Messanger was executing code inside Receiver synchronously!
            Assert.AreEqual(worker.ProductionArg, nameof(Messanger));

            await sequencer.WhenAll();            // wait for all tasks to complete

            Assert.DoesNotThrow(() => sequencer.TryReThrowException());
        }
        public async Task DisposeBasicTest()
        {
            var tickGenerator = new TickGenerator(10);

            ISequencerUC sequencer =
                SequencerUC
                .Construct()
                .Register(Steps.Notify, new StrategyOneOnOneUC())
            ;

            Action action = () =>
            {
                sequencer.Point(SeqPointTypeUC.Notify, Steps.Notify);
            };

            tickGenerator.Dispose();
            Task t = await tickGenerator.Disposed.WrapIntoTask();

            Assert.IsTrue(t.IsCompleted);
            Assert.IsFalse(t.IsCanceled);
            Assert.IsFalse(t.IsFaulted);

            Assert.ThrowsAsync <ObjectDisposedException>(async() => t = await tickGenerator.RegisterAsync(action).WrapIntoTask());
            Assert.IsTrue(t.IsCompleted);
            Assert.IsFalse(t.IsCanceled);
            Assert.IsFalse(t.IsFaulted);

            Assert.ThrowsAsync <ObjectDisposedException>(async() => t = await tickGenerator.UnRegisterAsync(action).WrapIntoTask());
            Assert.IsTrue(t.IsCompleted);
            Assert.IsFalse(t.IsCanceled);
            Assert.IsFalse(t.IsFaulted);

            await sequencer.WhenAll();

            sequencer.TryReThrowException();
        }
        public async Task Concurrent2RegisterResultTest()
        {
            ISequencerUC sequencer =
                SequencerUC
                .Construct()

                .Register(TimerProcessorSequencer.RegisterStatus, new StrategyOneOnOneUC())
                .Register(TimerProcessorSequencer.RegisterActiveProcessing, new StrategyOneOnOneUC())
                .Register(TimerProcessorSequencer.UnRegisterStatus, new StrategyOneOnOneUC())
                .Register(TimerProcessorSequencer.UnRegisterActiveProcessing, new StrategyOneOnOneUC())

                .Register(TimerProcessorSequencer.Processing, new StrategyOneOnOneUC())
                .Register(TimerProcessorSequencer.ExclusiveProcessing, new StrategyOneOnOneUC())
                .Register(TimerProcessorSequencer.BeginActiveProcessing, new StrategyOneOnOneUC())
                .Register(TimerProcessorSequencer.EndActiveProcessing, new StrategyOneOnOneUC())
                .Register(TimerProcessorSequencer.ActionsProcessing, new StrategyOneOnOneUC())
                .Register(TimerProcessorSequencer.ActionsProcessingCount, new StrategyOneOnOneUC())

                .Register(TimerProcessorSequencer.TryUpdateTimerBegin, new StrategyOneOnOneUC())
                .Register(TimerProcessorSequencer.TryUpdateTimerEnd, new StrategyOneOnOneUC())

                .Register(TimerProcessorSequencer.CallBackProcessing, new StrategyOneOnOneUC())
                //.Register(TimerProcessorSequencer.CallBackProcessing, new StrategyOneOnOneUC())
                //.Register(TimerProcessorSequencer.CallBackProcessing, new StrategyOneOnOneUC())
                //.Register(TimerProcessorSequencer.CallBackProcessing, new StrategyOneOnOneUC())
            ;

            var timeprocessor = new TimerProcessor(10, new RealTimeSource(), sequencer);


            var tt = Task.Run(() => timeprocessor.RegisterResultAsync(TimeSpan.FromMilliseconds(10000), new object()).WrapIntoTask());

            var rStatus = await sequencer.TestPointAsync(TimerProcessorSequencer.RegisterStatus);

            Assert.AreEqual(TimerProcessorStatus.Operating, rStatus.ProductionArg);
            var rActiveProcesing = await sequencer.TestPointAsync(TimerProcessorSequencer.RegisterActiveProcessing);

            Assert.AreEqual(false, rActiveProcesing.ProductionArg);

            var processing = await sequencer.TestPointAsync(TimerProcessorSequencer.Processing);

            var processingResult = (TimerProcessor.ProcessingResult)processing.ProductionArg;

            Assert.AreEqual(TimerProcessor.ProcessingResult.Processed, processingResult);

            var exclusiveProcessing = await sequencer.TestPointAsync(TimerProcessorSequencer.ExclusiveProcessing);

            exclusiveProcessing.Complete();

            var beginActiveProcessing = await sequencer.TestPointAsync(TimerProcessorSequencer.BeginActiveProcessing);

            beginActiveProcessing.Complete();

            var actionProcessing = await sequencer.TestPointAsync(TimerProcessorSequencer.ActionsProcessing);

            actionProcessing.Complete();
            Assert.AreEqual(false, actionProcessing.ProductionArg);

            var updateTimerBegin = await sequencer.TestPointAsync(TimerProcessorSequencer.TryUpdateTimerBegin);

            updateTimerBegin.Complete();
            Assert.AreEqual(TimerProcessorTimerStatus.None, updateTimerBegin.ProductionArg);

            var updateTimerEnd = await sequencer.TestPointAsync(TimerProcessorSequencer.TryUpdateTimerEnd);

            updateTimerEnd.Complete();
            Assert.AreEqual(TimerProcessorTimerStatus.Activate | TimerProcessorTimerStatus.IsActive | TimerProcessorTimerStatus.Changed, updateTimerEnd.ProductionArg);

            var endActiveProcessing = await sequencer.TestPointAsync(TimerProcessorSequencer.EndActiveProcessing);

            endActiveProcessing.Complete();
            Assert.AreEqual(TimerProcessorStatus.Operating, endActiveProcessing.ProductionArg);


            Task <TaskCompletionSource <object> > t = await tt;

            Assert.IsTrue(t.IsCompleted);
            Assert.IsFalse(t.IsCanceled);
            Assert.IsFalse(t.IsFaulted);
            TaskCompletionSource <object> tcs = t.Result;

            for (int i = 0; i < 10; i++)
            {
                var callBackProcessing = await sequencer.TestPointAsync(TimerProcessorSequencer.CallBackProcessing);

                callBackProcessing.Complete();

                var processingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.Processing);

                var processingCycleResult = (TimerProcessor.ProcessingResult)processingCycle.ProductionArg;
                Assert.AreEqual(TimerProcessor.ProcessingResult.Processed, processingCycleResult);

                var exclusiveProcessingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.ExclusiveProcessing);

                exclusiveProcessingCycle.Complete();

                var beginActiveProcessingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.BeginActiveProcessing);

                beginActiveProcessingCycle.Complete();

                var actionProcessingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.ActionsProcessing);

                actionProcessingCycle.Complete();
                Assert.AreEqual(true, actionProcessingCycle.ProductionArg);

                var actionProcessingCountCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.ActionsProcessingCount);

                Assert.AreEqual(1, actionProcessingCountCycle.ProductionArg);
                //for (int j = 0; j < (int)actionProcessingCountCycle.ProductionArg; j++)
                //{
                //	await sequencer.TestPointAsync(Steps.Notify);
                //}

                var updateTimerBeginCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.TryUpdateTimerBegin);

                updateTimerBeginCycle.Complete();
                Assert.AreEqual(TimerProcessorTimerStatus.IsActive, updateTimerBeginCycle.ProductionArg);

                var updateTimerEndCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.TryUpdateTimerEnd);

                updateTimerEndCycle.Complete();
                Assert.AreEqual(TimerProcessorTimerStatus.Activate | TimerProcessorTimerStatus.IsActive, updateTimerEndCycle.ProductionArg);

                var endActiveProcessingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.EndActiveProcessing);

                endActiveProcessingCycle.Complete();
                Assert.AreEqual(TimerProcessorStatus.Operating, endActiveProcessingCycle.ProductionArg);
            }

            for (int i = 0; i < 1; i++)
            {
                //var callBackProcessing =
                await sequencer.TestPointAsync(TimerProcessorSequencer.CallBackProcessing);

                //callBackProcessing.Complete();

                //var processingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.Processing);
                //var processingCycleResult = (TimerProcessor.ProcessingResult)processingCycle.ProductionArg;
                //Assert.AreEqual(TimerProcessor.ProcessingResult.Processed, processingCycleResult);

                //var exclusiveProcessingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.ExclusiveProcessing);
                //exclusiveProcessingCycle.Complete();

                //var beginActiveProcessingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.BeginActiveProcessing);
                //beginActiveProcessingCycle.Complete();

                //ActiveProcessing
                tt = Task.Run(() => timeprocessor.UnRegisterAsync(tcs).WrapIntoTask());

                var rStatusCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.UnRegisterStatus);

                Assert.AreEqual(TimerProcessorStatus.Operating, rStatusCycle.ProductionArg);
                var rActiveProcesingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.UnRegisterActiveProcessing);

                Assert.AreEqual(false, rActiveProcesingCycle.ProductionArg);

                var processingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.Processing);

                var processingCycleResult = (TimerProcessor.ProcessingResult)processingCycle.ProductionArg;
                Assert.AreEqual(TimerProcessor.ProcessingResult.Processed, processingCycleResult);

                var exclusiveProcessingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.ExclusiveProcessing);

                exclusiveProcessingCycle.Complete();

                var beginActiveProcessingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.BeginActiveProcessing);

                beginActiveProcessingCycle.Complete();

                var actionProcessingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.ActionsProcessing);

                actionProcessingCycle.Complete();
                Assert.AreEqual(false, actionProcessingCycle.ProductionArg);

                //var actionProcessingCountCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.ActionsProcessingCount);
                //Assert.AreEqual(1, actionProcessingCountCycle.ProductionArg);
                //for (int j = 0; j < (int)actionProcessingCountCycle.ProductionArg; j++)
                //{
                //	await sequencer.TestPointAsync(Steps.Notify);
                //}

                var updateTimerBeginCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.TryUpdateTimerBegin);

                updateTimerBeginCycle.Complete();
                Assert.AreEqual(TimerProcessorTimerStatus.IsActive, updateTimerBeginCycle.ProductionArg);

                var updateTimerEndCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.TryUpdateTimerEnd);

                updateTimerEndCycle.Complete();
                Assert.AreEqual(TimerProcessorTimerStatus.Changed, updateTimerEndCycle.ProductionArg);

                var endActiveProcessingCycle = await sequencer.TestPointAsync(TimerProcessorSequencer.EndActiveProcessing);

                endActiveProcessingCycle.Complete();
                Assert.AreEqual(TimerProcessorStatus.Operating, endActiveProcessingCycle.ProductionArg);
            }


            t = await tt;
            Assert.IsTrue(t.IsCompleted);
            Assert.IsFalse(t.IsCanceled);
            Assert.IsFalse(t.IsFaulted);

            await sequencer.WhenAll();

            sequencer.TryReThrowException();
        }
        public async Task ConcurrentSequencing()
        {
            StepConcurrentSequencing = 0;

            ISequencerUC sequencer =
                SequencerUC
                .Construct()
                .Register(ConcurrentSequencingPhase.Begin, new StrategyOneOnOneUC())
                .Register(ConcurrentSequencingPhase.EnteringSimpleLock, new StrategyOneOnOneUC())
                .Register(ConcurrentSequencingPhase.Locked, new StrategyOneOnOneUC())
                .Register(ConcurrentSequencingPhase.LockedNotify, new StrategyOneOnOneUC())
                .Register(ConcurrentSequencingPhase.End, new StrategyOneOnOneUC())
            ;

            //StrategyOneOnOneUC each production code point(per thread) is matched to unit test point
            //that is per point and per thread in production code

            IAsyncLockUC Lock = new AsyncSpinLockUC();

            //start first worker
            sequencer.Run(seq => ConcurrentSequencingWorker(Lock, sequencer));
            //await first worker to get to Begin point
            var Begin1 = await sequencer.TestPointAsync(ConcurrentSequencingPhase.Begin);

            //first worker at Begin point


            //start second worker
            sequencer.Run(seq => ConcurrentSequencingWorker(Lock, sequencer));
            //await second worker to get to Begin point
            var Begin2 = await sequencer.TestPointAsync(ConcurrentSequencingPhase.Begin);

            //second worker at Begin point

            //allow first worker to continue to Locked point
            Begin1.Complete();
            //Begin1.Fail(new Exception("Hmmmm"));
            var notify1 = await sequencer.TestPointAsync(ConcurrentSequencingPhase.EnteringSimpleLock);

            //await first worker to get to Locked point
            var Locked1 = await sequencer.TestPointAsync(ConcurrentSequencingPhase.Locked);

            Assert.AreEqual(0, Locked1.ProductionArg);
            //first worker at Locked point

            //spinlock is locked, first worker has exclusive access

            //allow first worker to continue to Locked point it will spin until lock get opened
            Begin2.Complete();

            //this helps us to ensure we do not need thread waiting,
            //notification are in production code completed awaiters,
            //immediatelly executiong what is next after the await on notification,
            //so it is known to be actively running thread!
            var notify2 = await sequencer.TestPointAsync(ConcurrentSequencingPhase.EnteringSimpleLock);

            //second worker has entered spinlock as is spinning!

            //let first worker leave spin lock
            Locked1.Complete();

            //first thread is leaving the spinlock, but before leaving step value will be recorderd
            //second thread is spinning to get inside
            //LockedNotify can be checked if the recorded step value was 1 => thread 1 inside, thread 2 attempting to get inside
            var LockedNotify1 = await sequencer.TestPointAsync(ConcurrentSequencingPhase.LockedNotify);

            Assert.AreEqual(1, LockedNotify1.ProductionArg);             //this is checking concurrency correctness, as threads were highly probably active during checking


            //await first worker at End point
            var End1 = await sequencer.TestPointAsync(ConcurrentSequencingPhase.End);

            //first worker released spinlock
            End1.Complete();
            //first worker done

            //await second worker at Locked point
            var Locked2 = await sequencer.TestPointAsync(ConcurrentSequencingPhase.Locked);

            //let second worker to continue to End point
            Locked2.Complete();

            var LockedNotify2 = await sequencer.TestPointAsync(ConcurrentSequencingPhase.LockedNotify);

            Assert.AreEqual(0, LockedNotify2.ProductionArg);

            //await second worker at the End point
            var End2 = await sequencer.TestPointAsync(ConcurrentSequencingPhase.End);

            //second worker released spinlock
            End2.Complete();
            //second worker done

            await sequencer.WhenAll();

            sequencer.TryReThrowException();
        }
        public async Task ConcurrentTest()
        {
            ISequencerUC sequencer =
                SequencerUC
                .Construct()
                .Register(Steps.Notify, new StrategyOneOnOneUC())

                .Register(TickGeneratorSequencer.RegisterStatus, new StrategyOneOnOneUC())
                .Register(TickGeneratorSequencer.RegisterActiveProcessing, new StrategyOneOnOneUC())
                .Register(TickGeneratorSequencer.UnRegisterStatus, new StrategyOneOnOneUC())
                .Register(TickGeneratorSequencer.UnRegisterActiveProcessing, new StrategyOneOnOneUC())

                .Register(TickGeneratorSequencer.Processing, new StrategyOneOnOneUC())
                .Register(TickGeneratorSequencer.ExclusiveProcessing, new StrategyOneOnOneUC())
                .Register(TickGeneratorSequencer.BeginActiveProcessing, new StrategyOneOnOneUC())
                .Register(TickGeneratorSequencer.EndActiveProcessing, new StrategyOneOnOneUC())
                .Register(TickGeneratorSequencer.ActionsProcessing, new StrategyOneOnOneUC())
                .Register(TickGeneratorSequencer.ActionsProcessingCount, new StrategyOneOnOneUC())

                .Register(TickGeneratorSequencer.TryUpdateTimerBegin, new StrategyOneOnOneUC())
                .Register(TickGeneratorSequencer.TryUpdateTimerEnd, new StrategyOneOnOneUC())

                .Register(TickGeneratorSequencer.CallBackProcessing, new StrategyOneOnOneUC())
                //.Register(TickGeneratorSequencer.CallBackProcessing, new StrategyOneOnOneUC())
                //.Register(TickGeneratorSequencer.CallBackProcessing, new StrategyOneOnOneUC())
                //.Register(TickGeneratorSequencer.CallBackProcessing, new StrategyOneOnOneUC())
            ;

            var tickGenerator = new TickGenerator(10, sequencer);

            Action action = () =>
            {
                sequencer.Point(SeqPointTypeUC.Notify, Steps.Notify);
            };

            Task <Task> tt = Task.Run(() => tickGenerator.RegisterAsync(action).WrapIntoTask());

            var rStatus = await sequencer.TestPointAsync(TickGeneratorSequencer.RegisterStatus);

            Assert.AreEqual(TickGeneratorStatus.Operating, rStatus.ProductionArg);
            var rActiveProcesing = await sequencer.TestPointAsync(TickGeneratorSequencer.RegisterActiveProcessing);

            Assert.AreEqual(false, rActiveProcesing.ProductionArg);

            var processing = await sequencer.TestPointAsync(TickGeneratorSequencer.Processing);

            var processingResult = (TickGenerator.ProcessingResult)processing.ProductionArg;

            Assert.AreEqual(TickGenerator.ProcessingResult.Processed, processingResult);

            var exclusiveProcessing = await sequencer.TestPointAsync(TickGeneratorSequencer.ExclusiveProcessing);

            exclusiveProcessing.Complete();

            var beginActiveProcessing = await sequencer.TestPointAsync(TickGeneratorSequencer.BeginActiveProcessing);

            beginActiveProcessing.Complete();

            var actionProcessing = await sequencer.TestPointAsync(TickGeneratorSequencer.ActionsProcessing);

            actionProcessing.Complete();
            Assert.AreEqual(false, actionProcessing.ProductionArg);

            var updateTimerBegin = await sequencer.TestPointAsync(TickGeneratorSequencer.TryUpdateTimerBegin);

            updateTimerBegin.Complete();
            Assert.AreEqual(TickGeneratorTimerStatus.None, updateTimerBegin.ProductionArg);

            var updateTimerEnd = await sequencer.TestPointAsync(TickGeneratorSequencer.TryUpdateTimerEnd);

            updateTimerEnd.Complete();
            Assert.AreEqual(TickGeneratorTimerStatus.Activate | TickGeneratorTimerStatus.IsActive | TickGeneratorTimerStatus.Changed, updateTimerEnd.ProductionArg);

            var endActiveProcessing = await sequencer.TestPointAsync(TickGeneratorSequencer.EndActiveProcessing);

            endActiveProcessing.Complete();
            Assert.AreEqual(TickGeneratorStatus.Operating, endActiveProcessing.ProductionArg);


            Task t = await tt;

            Assert.IsTrue(t.IsCompleted);
            Assert.IsFalse(t.IsCanceled);
            Assert.IsFalse(t.IsFaulted);


            for (int i = 0; i < 10; i++)
            {
                var callBackProcessing = await sequencer.TestPointAsync(TickGeneratorSequencer.CallBackProcessing);

                callBackProcessing.Complete();

                var processingCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.Processing);

                var processingCycleResult = (TickGenerator.ProcessingResult)processingCycle.ProductionArg;
                Assert.AreEqual(TickGenerator.ProcessingResult.Processed, processingCycleResult);

                var exclusiveProcessingCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.ExclusiveProcessing);

                exclusiveProcessingCycle.Complete();

                var beginActiveProcessingCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.BeginActiveProcessing);

                beginActiveProcessingCycle.Complete();

                var actionProcessingCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.ActionsProcessing);

                actionProcessingCycle.Complete();
                Assert.AreEqual(true, actionProcessingCycle.ProductionArg);

                var actionProcessingCountCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.ActionsProcessingCount);

                Assert.AreEqual(1, actionProcessingCountCycle.ProductionArg);
                for (int j = 0; j < (int)actionProcessingCountCycle.ProductionArg; j++)
                {
                    await sequencer.TestPointAsync(Steps.Notify);
                }

                var updateTimerBeginCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.TryUpdateTimerBegin);

                updateTimerBeginCycle.Complete();
                Assert.AreEqual(TickGeneratorTimerStatus.IsActive, updateTimerBeginCycle.ProductionArg);

                var updateTimerEndCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.TryUpdateTimerEnd);

                updateTimerEndCycle.Complete();
                Assert.AreEqual(TickGeneratorTimerStatus.Activate | TickGeneratorTimerStatus.IsActive, updateTimerEndCycle.ProductionArg);

                var endActiveProcessingCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.EndActiveProcessing);

                endActiveProcessingCycle.Complete();
                Assert.AreEqual(TickGeneratorStatus.Operating, endActiveProcessingCycle.ProductionArg);
            }

            for (int i = 0; i < 1; i++)
            {
                var callBackProcessing = await sequencer.TestPointAsync(TickGeneratorSequencer.CallBackProcessing);

                callBackProcessing.Complete();

                var processingCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.Processing);

                var processingCycleResult = (TickGenerator.ProcessingResult)processingCycle.ProductionArg;
                Assert.AreEqual(TickGenerator.ProcessingResult.Processed, processingCycleResult);

                var exclusiveProcessingCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.ExclusiveProcessing);

                exclusiveProcessingCycle.Complete();

                var beginActiveProcessingCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.BeginActiveProcessing);

                beginActiveProcessingCycle.Complete();

                //ActiveProcessing
                tt = Task.Run(() => tickGenerator.UnRegisterAsync(action).WrapIntoTask());

                var rStatusCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.UnRegisterStatus);

                Assert.AreEqual(TickGeneratorStatus.Operating, rStatusCycle.ProductionArg);
                var rActiveProcesingCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.UnRegisterActiveProcessing);

                Assert.AreEqual(true, rActiveProcesingCycle.ProductionArg);

                var actionProcessingCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.ActionsProcessing);

                actionProcessingCycle.Complete();
                Assert.AreEqual(true, actionProcessingCycle.ProductionArg);

                var actionProcessingCountCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.ActionsProcessingCount);

                Assert.AreEqual(1, actionProcessingCountCycle.ProductionArg);
                for (int j = 0; j < (int)actionProcessingCountCycle.ProductionArg; j++)
                {
                    await sequencer.TestPointAsync(Steps.Notify);
                }

                var updateTimerBeginCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.TryUpdateTimerBegin);

                updateTimerBeginCycle.Complete();
                Assert.AreEqual(TickGeneratorTimerStatus.IsActive, updateTimerBeginCycle.ProductionArg);

                var updateTimerEndCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.TryUpdateTimerEnd);

                updateTimerEndCycle.Complete();
                Assert.AreEqual(TickGeneratorTimerStatus.Changed, updateTimerEndCycle.ProductionArg);

                var endActiveProcessingCycle = await sequencer.TestPointAsync(TickGeneratorSequencer.EndActiveProcessing);

                endActiveProcessingCycle.Complete();
                Assert.AreEqual(TickGeneratorStatus.Operating, endActiveProcessingCycle.ProductionArg);
            }


            t = await tt;
            Assert.IsTrue(t.IsCompleted);
            Assert.IsFalse(t.IsCanceled);
            Assert.IsFalse(t.IsFaulted);

            await sequencer.WhenAll();

            sequencer.TryReThrowException();
        }
Beispiel #11
0
        public async Task ThreadAbortDuringUnmanagedCall()
        {
            object objLock = new object();

            ISequencerUC sequencer =
                SequencerUC
                .Construct()
                .Register(Worker.BeforeLock, new StrategyOneOnOneUC())
                .Register(Worker.Locked, new StrategyOneOnOneUC())
                .Register(Worker.Stuck, new StrategyOneOnOneUC())
            ;

            sequencer.Run(seq => LockedWorker(seq, objLock));            //run 1st thread
            sequencer.Run(seq => LockedWorker(seq, objLock));            //run 2nd thread
            sequencer.Run(seq => LockedWorker(seq, objLock));            //run 3rd thread

            var test1 = await sequencer.TestPointAsync(Worker.BeforeLock);

            var test2 = await sequencer.TestPointAsync(Worker.BeforeLock);

            var test3 = await sequencer.TestPointAsync(Worker.BeforeLock);

            var th1 = test1.ProductionArg as Thread;
            var th2 = test2.ProductionArg as Thread;
            var th3 = test3.ProductionArg as Thread;
            //only one gets inside lock
            await sequencer.TestPointAsync(Worker.Locked);

            //and will stuck intentionally
            var intentionallyStuck = await sequencer.TestPointAsync(Worker.Stuck);

            await Task.Delay(100);

            await Task.Delay(100);

            await Task.Delay(100);

            await Task.Delay(100);

            await Task.Delay(100);

            await Task.Delay(100);

            try
            {
                Thread thread = intentionallyStuck.ProductionArg as Thread;
                await Task.Delay(100);

                thread?.Abort();
                th1?.Abort();
                th2?.Abort();
                th3?.Abort();
                while (true)
                {
                    try
                    {
                        await Task.Delay(100);

                        sequencer.TryReThrowException();
                    }
                    catch (Exception ex)
                    {
                        Assert.Warn(ex.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                Assert.Warn(ex.Message);
                throw;
            }
        }