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(); } }
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); } }
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); }
public EntryBlockUC Enter() { using (SpinLockUC.Enter()) { if (!Locked) { Locked = true; return(new EntryBlockUC(EntryTypeUC.Exclusive, EntryCompletion)); } } }
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(); }
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); }
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(); }
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) }); }