public void API_TryWrappedInvoke() { var atomicInt = new LockFreeInt32(); var target = new AtomicDelegate <Func <int, int> >(); Assert.AreEqual((false, default(int)), target.TryWrappedInvoke(f => f(10))); target.Set(i => atomicInt.Add(i).CurrentValue); Assert.AreEqual((true, 10), target.TryWrappedInvoke(f => f(10))); Assert.AreEqual(10, atomicInt.Value); Assert.AreEqual(true, target.TryWrappedInvoke((Action <Func <int, int> >)(f => f(10)))); Assert.AreEqual(20, atomicInt.Value); target.Set(null); Assert.AreEqual(false, target.TryWrappedInvoke((Action <Func <int, int> >)(f => f(10)))); Assert.AreEqual(20, atomicInt.Value); // Context-consuming variants atomicInt.Set(0); target.Set(null); Assert.AreEqual((false, default(int)), target.TryWrappedInvoke((f, ctx) => f(ctx), 10)); target.Set(i => atomicInt.Add(i).CurrentValue); Assert.AreEqual((true, 10), target.TryWrappedInvoke((f, ctx) => f(ctx), 10)); Assert.AreEqual(10, atomicInt.Value); Assert.AreEqual(true, target.TryWrappedInvoke((Action <Func <int, int>, int>)((f, ctx) => f(ctx)), 10)); Assert.AreEqual(20, atomicInt.Value); target.Set(null); Assert.AreEqual(false, target.TryWrappedInvoke((Action <Func <int, int>, int>)((f, ctx) => f(ctx)), 10)); Assert.AreEqual(20, atomicInt.Value); }
public void API_TryDynamicInvoke() { var atomicInt = new LockFreeInt32(); var targetA = new AtomicDelegate <Action <int> >(); Assert.AreEqual((false, (object)null), targetA.TryDynamicInvoke(10)); targetA.Set(i => atomicInt.Add(i)); Assert.AreEqual((true, (object)null), targetA.TryDynamicInvoke(300)); Assert.Throws <TargetParameterCountException>(() => targetA.TryDynamicInvoke()); Assert.Throws <ArgumentException>(() => targetA.TryDynamicInvoke("")); Assert.Throws <TargetParameterCountException>(() => targetA.TryDynamicInvoke(3, 3)); var targetB = new AtomicDelegate <Func <int, int> >(); Assert.AreEqual((false, (object)null), targetB.TryDynamicInvoke(10)); targetB.Set(i => atomicInt.Add(i).CurrentValue); var invokeRes = targetB.TryDynamicInvoke(300); Assert.AreEqual(true, invokeRes.DelegateWasInvoked); Assert.AreEqual(600, (int)invokeRes.Result); Assert.Throws <TargetParameterCountException>(() => targetB.TryDynamicInvoke()); Assert.Throws <ArgumentException>(() => targetB.TryDynamicInvoke("")); Assert.Throws <TargetParameterCountException>(() => targetB.TryDynamicInvoke(3, 3)); }
void WithInlined_Entry() { for (var i = 0; i < NumIterations; ++i) { var incResult = _inlined.Increment(); Assert(incResult.CurrentValue == incResult.PreviousValue + 1); SimulateContention(ContentionLevel.B_Moderate); var addResult = _inlined.Add(10); Assert(addResult.CurrentValue == addResult.PreviousValue + 10); SimulateContention(ContentionLevel.B_Moderate); var subResult = _inlined.Subtract(9); Assert(subResult.CurrentValue == subResult.PreviousValue - 9); SimulateContention(ContentionLevel.B_Moderate); var multResult = _inlined.MultiplyBy(3); Assert(multResult.CurrentValue == multResult.PreviousValue * 3); SimulateContention(ContentionLevel.B_Moderate); var divResult = _inlined.DivideBy(4); Assert(divResult.CurrentValue == divResult.PreviousValue / 4); SimulateContention(ContentionLevel.B_Moderate); var decResult = _inlined.Decrement(); Assert(decResult.CurrentValue == decResult.PreviousValue - 1); SimulateContention(ContentionLevel.B_Moderate); var value = _inlined.Value; var exchVal = _inlined.Exchange(value + 3); _inlined.Value = exchVal.PreviousValue - 3; } }
void WithCustomInt_Entry() { const int Bitmask = 0b101010101; for (var i = 0; i < NumIterations; ++i) { var incResult = _customInt32.Increment(); Assert(incResult.CurrentValue == incResult.PreviousValue + 1); var addResult = _customInt32.Add(10); Assert(addResult.CurrentValue == addResult.PreviousValue + 10); var subResult = _customInt32.Subtract(9); Assert(subResult.CurrentValue == subResult.PreviousValue - 9); var multResult = _customInt32.MultiplyBy(3); Assert(multResult.CurrentValue == multResult.PreviousValue * 3); var divResult = _customInt32.DivideBy(4); Assert(divResult.CurrentValue == divResult.PreviousValue / 4); var decResult = _customInt32.Decrement(); Assert(decResult.CurrentValue == decResult.PreviousValue - 1); var exchangeResult = _customInt32.Exchange(curVal => curVal & Bitmask); Assert(exchangeResult.CurrentValue == (exchangeResult.PreviousValue & Bitmask)); } }
public void TryInvokeTryWrappedInvokeTryDynamicInvoke() { const int NumIterations = 40_000; const int NumCombinesPerIteration = 3; const int ActionInputValue = 3; var runner = new ConcurrentTestCaseRunner <AtomicDelegate <Func <int, int> > >(() => new AtomicDelegate <Func <int, int> >()); var counter = new LockFreeInt32(); var writerCount = new LockFreeInt32(); var action = new Func <int, int>(n => counter.Add(n).CurrentValue); CancellationTokenSource cts = null; runner.GlobalSetUp = (_, threadConfig) => { writerCount.Value = threadConfig.WriterThreadCount; cts = new CancellationTokenSource(); }; runner.ExecuteSingleReaderTests( writerFunction: target => { for (var j = 0; j < NumIterations; j++) { for (var i = 0; i < NumCombinesPerIteration; i++) { target.Combine(action); } for (var i = 0; i < NumCombinesPerIteration; i++) { target.Remove(action); } } cts.Cancel(); }, readerFunction: target => { var numWriters = writerCount.Value; while (!cts.IsCancellationRequested) { TestTryInvoke(); TestWrappedInvoke(); TestDynamicInvoke(); void TestTryInvoke() { var curCounterValue = counter.Value; var result = target.TryInvoke(ActionInputValue); if (result.DelegateWasInvoked) { TestResult(curCounterValue, result.Result); } else { FastAssertEqual(curCounterValue, counter.Value); } } void TestWrappedInvoke() { var curCounterValue = counter.Value; var result = target.TryWrappedInvoke(t => t(ActionInputValue)); if (result.DelegateWasInvoked) { TestResult(curCounterValue, result.Result); } else { FastAssertEqual(curCounterValue, counter.Value); } curCounterValue = counter.Value; result = target.TryWrappedInvoke((t, ctx) => t(ctx), ActionInputValue); if (result.DelegateWasInvoked) { TestResult(curCounterValue, result.Result); } else { FastAssertEqual(curCounterValue, counter.Value); } curCounterValue = counter.Value; var wasInvoked = target.TryWrappedInvoke(t => { t(ActionInputValue); }); if (wasInvoked) { TestResult(curCounterValue, counter.Value); } else { FastAssertEqual(curCounterValue, counter.Value); } curCounterValue = counter.Value; wasInvoked = target.TryWrappedInvoke((t, ctx) => { t(ctx); }, ActionInputValue); if (wasInvoked) { TestResult(curCounterValue, counter.Value); } else { FastAssertEqual(curCounterValue, counter.Value); } } void TestDynamicInvoke() { var curCounterValue = counter.Value; var result = target.TryDynamicInvoke(ActionInputValue); if (result.DelegateWasInvoked) { TestResult(curCounterValue, (int)result.Result); } else { FastAssertEqual(curCounterValue, counter.Value); } } void TestResult(int previousCounterValue, int invocationResult) { var diff = invocationResult - previousCounterValue; FastAssertTrue(diff >= 0 && diff <= NumCombinesPerIteration * numWriters * ActionInputValue); FastAssertTrue(invocationResult % ActionInputValue == 0); } } } ); }