Beispiel #1
0
        public void ConcurrentCorrectness()
        {
            SpinLockUC spinlock = new SpinLockUC();

            int index = 0;

            Task[] tasks =
                Enumerable
                .Range(0, Math.Max(Environment.ProcessorCount, 4))
                .Select(x => Task.Run(() =>
            {
                for (int i = 0; i < 100; i++)
                {
                    using (spinlock.Enter())
                    {
                        Assert.AreEqual(Interlocked.Increment(ref index), 1);
                        Thread.Sleep(1);
                        Assert.AreEqual(Interlocked.Decrement(ref index), 0);
                    }
                }
            }))
                .ToArray()
            ;

            Task.WaitAll(tasks);
        }
 public void SyncExceptionTestMethod(SpinLockUC spinlock)
 {
     using (spinlock.Enter())
     {
         throw new Exception();
     }
 }
Beispiel #3
0
        public void SingleThreadCorrectness()
        {
            SpinLockUC spinlock = new SpinLockUC();

            using (spinlock.Enter())
            {
            }

            using (EntryBlockUC entry = spinlock.Enter())
            {
                Assert.AreEqual(entry.EntryTypeUC, EntryTypeUC.Exclusive);
                Assert.IsTrue(entry.HasEntry);
            }

            using (EntryBlockUC entry = spinlock.TryEnter())
            {
                Assert.AreEqual(entry.EntryTypeUC, EntryTypeUC.Exclusive);
                Assert.IsTrue(entry.HasEntry);
                if (entry.HasEntry)
                {
                }
            }

            using (EntryBlockUC entry = spinlock.TryEnter(1))
            {
                Assert.AreEqual(entry.EntryTypeUC, EntryTypeUC.Exclusive);
                Assert.IsTrue(entry.HasEntry);
                if (entry.HasEntry)
                {
                }
            }

            EntryBlockUC entryOutsideUsing1 = spinlock.Enter();
            EntryBlockUC entryOutsideUsing2 = spinlock.TryEnter();
            EntryBlockUC entryOutsideUsing3 = spinlock.TryEnter(1);

            Assert.IsTrue(entryOutsideUsing1.HasEntry);
            Assert.IsFalse(entryOutsideUsing2.HasEntry);
            Assert.IsFalse(entryOutsideUsing3.HasEntry);

            Assert.IsTrue(entryOutsideUsing2 == EntryBlockUC.RefusedEntry);

            entryOutsideUsing1.Dispose();

            using (IEntryBlockUC entry = spinlock.Enter())
            {
                Assert.IsTrue(entry.HasEntry);
            }

            using (IEntryBlockUC entry = spinlock.TryEnter())
            {
                Assert.IsTrue(entry.HasEntry);
            }

            using (IEntryBlockUC entry = spinlock.TryEnter(1))
            {
                Assert.IsTrue(entry.HasEntry);
            }
        }
Beispiel #4
0
 private static void ConcurrentSequencingWorker(SpinLockUC spinLock, ISequencerUC sequencer)
 {
     sequencer.Point(SeqPointTypeUC.Match, ConcurrentSequencingPhase.Begin);
     sequencer.Point(SeqPointTypeUC.Notify, ConcurrentSequencingPhase.EnteringSpinLock, Interlocked.Increment(ref StepConcurrentSequencing));
     using (spinLock.Enter())
     {
         sequencer.Point(SeqPointTypeUC.Match, ConcurrentSequencingPhase.Locked, Interlocked.Decrement(ref StepConcurrentSequencing));
         sequencer.Point(SeqPointTypeUC.Notify, ConcurrentSequencingPhase.LockedNotify, Interlocked.Add(ref StepConcurrentSequencing, 0));
     }
     sequencer.Point(SeqPointTypeUC.Match, ConcurrentSequencingPhase.End);
 }
Beispiel #5
0
 public EntryBlockUC Enter()
 {
     using (SpinLockUC.Enter())
     {
         if (!Locked)
         {
             Locked = true;
             return(new EntryBlockUC(EntryTypeUC.Exclusive, EntryCompletion));
         }
     }
 }
Beispiel #6
0
        public void SyncExceptionReleasingLockTest()
        {
            ILockUC spinlock = new SpinLockUC();

            Assert.Throws <Exception>(() => SyncExceptionTestMethod(spinlock));
            EntryBlockUC entry = spinlock.TryEnter();

            Assert.IsTrue(entry.HasEntry);
            entry.Dispose();
            entry = spinlock.TryEnter();
            Assert.IsTrue(entry.HasEntry);
            entry.Dispose();
        }
Beispiel #7
0
        private static async Task ConcurrentSequencingAsyncWorker(SpinLockUC spinLock, ISequencerUC sequencer)
        {
            await sequencer.PointAsync(SeqPointTypeUC.Match, ConcurrentSequencingPhaseAsync.Begin);

            await sequencer.PointAsync(SeqPointTypeUC.Notify, ConcurrentSequencingPhaseAsync.EnteringSpinLock, Interlocked.Increment(ref StepConcurrentSequencingAsync));

            using (spinLock.Enter())
            {
                await sequencer.PointAsync(SeqPointTypeUC.Match, ConcurrentSequencingPhaseAsync.Locked, Interlocked.Decrement(ref StepConcurrentSequencingAsync));

                await sequencer.PointAsync(SeqPointTypeUC.Notify, ConcurrentSequencingPhaseAsync.LockedNotify, Interlocked.Add(ref StepConcurrentSequencingAsync, 0));
            }
            await sequencer.PointAsync(SeqPointTypeUC.Match, ConcurrentSequencingPhaseAsync.End);
        }
Beispiel #8
0
        public async Task ConcurrentSequencing()
        {
            StepConcurrentSequencing = 0;

            ISequencerUC sequencer =
                SequencerUC
                .Construct()
                .Register(ConcurrentSequencingPhase.Begin, new StrategyOneOnOneUC())
                .Register(ConcurrentSequencingPhase.EnteringSpinLock, 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

            SpinLockUC spinlock = new SpinLockUC();

            //start first worker
            sequencer.Run(seq => ConcurrentSequencingWorker(spinlock, 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(spinlock, 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.EnteringSpinLock);

            //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.EnteringSpinLock);

            //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();
        }
Beispiel #9
0
 private void Exit()
 {
     using (SpinLockUC.Enter())
     {
     }
 }
 private static void ConcurrentSequencingConditionalWorker(ISequencerUC sequencer, SpinLockUC spinLock)
 {
     ConditionalSequencerUC.Point(sequencer, SeqPointTypeUC.Match, ConcurrentSequencingPhaseConditional.Begin);
     ConditionalSequencerUC.Point(sequencer, SeqPointTypeUC.Notify, ConcurrentSequencingPhaseConditional.EnteringSpinLock, Interlocked.Increment(ref StepConcurrentSequencingConditional));
     using (spinLock.Enter())
     {
         ConditionalSequencerUC.Point(sequencer, SeqPointTypeUC.Match, ConcurrentSequencingPhaseConditional.Locked, Interlocked.Decrement(ref StepConcurrentSequencingConditional));
         ConditionalSequencerUC.Point(sequencer, SeqPointTypeUC.Notify, ConcurrentSequencingPhaseConditional.LockedNotify, Interlocked.Add(ref StepConcurrentSequencingConditional, 0));
     }
     ConditionalSequencerUC.Point(sequencer, SeqPointTypeUC.Match, ConcurrentSequencingPhaseConditional.End);
 }
        public async Task HeavySpinLockUC(BenchInfo info, IPerfCounterCollectorUC perfColletor, TimeSpan ts, int spin, int threads)
        {
            ILockUC Lock = new SpinLockUC();

            await GeneralBenchmark(perfColletor, info.Name, threads, i => Lock, (i, perfCntr, sync) => new BenchInstance[] { new SimpleLockWorker(perfCntr, Lock, ts, spin, string.Empty) });
        }