public void FastExchange() { const int NumIterations = 3_000_000; var atomicIntA = new AtomicInt(0); var atomicIntB = new AtomicInt(0); var runner = NewRunner(new DummyImmutableVal(0, 0)); // (T) runner.GlobalSetUp = (_, __) => { atomicIntA.Set(0); atomicIntB.Set(0); }; runner.AllThreadsTearDown = target => { AssertAreEqual(NumIterations, target.Value.Alpha); AssertAreEqual(NumIterations, target.Value.Bravo); }; runner.ExecuteContinuousSingleWriterCoherencyTests( target => { var newA = atomicIntA.Increment().CurrentValue; var newB = atomicIntB.Increment().CurrentValue; var newValue = new DummyImmutableVal(newA, newB); var prev = target.FastExchange(newValue); AssertAreEqual(prev.Alpha, newA - 1); AssertAreEqual(prev.Bravo, newB - 1); }, NumIterations, target => target.Value, (prev, cur) => { AssertTrue(prev.Alpha <= cur.Alpha); AssertTrue(prev.Bravo <= cur.Bravo); } ); runner.GlobalSetUp = null; runner.AllThreadsTearDown = null; }
public void Assert_Coherency_Swap() { const int NumIterations = 3_000_000; var atomicIntA = new LockFreeInt32(0); var atomicIntB = new LockFreeInt32(0); var runner = NewRunner(new DummyImmutableVal(0, 0)); runner.GlobalSetUp = (_, __) => { atomicIntA.Set(0); atomicIntB.Set(0); }; runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.Alpha); FastAssertEqual(NumIterations, target.Value.Bravo); }; runner.ExecuteContinuousSingleWriterCoherencyTests( target => { var newA = atomicIntA.IncrementAndGet(); var newB = atomicIntB.IncrementAndGet(); var newValue = new DummyImmutableVal(newA, newB); var prev = target.Swap(newValue); FastAssertEqual(prev.Alpha, newA - 1); FastAssertEqual(prev.Bravo, newB - 1); }, NumIterations, target => target.Value, (prev, cur) => { FastAssertTrue(prev.Alpha <= cur.Alpha); FastAssertTrue(prev.Bravo <= cur.Bravo); } ); runner.GlobalSetUp = null; runner.AllThreadsTearDown = null; }
public void Assert_Coherency_TrySwap() { const int NumIterations = 2_000_000; var runner = NewRunner(new DummyImmutableVal(0, 0)); runner.ExecuteContinuousCoherencyTests( target => { var curValue = target.Value; var newValue = new DummyImmutableVal(0, curValue.Bravo + 1); target.TrySwap(newValue, curValue); }, NumIterations, target => target.Value, (prev, cur) => FastAssertTrue(cur.Bravo >= prev.Bravo) ); }
public void TryExchangeWithContext() { const int NumIterations = 300_000; var runner = NewRunner(new DummyImmutableVal(0, 0)); // (T, Func<T, T, TContext, bool>) runner.AllThreadsTearDown = target => { AssertAreEqual(NumIterations, target.Value.Alpha); AssertAreEqual(-1 * NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var newValue = new DummyImmutableVal(curValue.Alpha + 1, curValue.Bravo - 1); var(wasSet, prevValue, setValue) = target.TryExchange(newValue, (c, n, ctx) => c.Alpha + ctx == n.Alpha && c.Bravo - ctx == n.Bravo, 1); if (wasSet) { AssertAreEqual(curValue, prevValue); AssertAreEqual(newValue, setValue); } else { AssertAreNotEqual(curValue, prevValue); AssertAreEqual(setValue, prevValue); } } } ); runner.AllThreadsTearDown = null; // (Func<T, TContext, T>, T) runner.ExecuteFreeThreadedTests( target => { var curValue = target.Value; var(wasSet, prevValue, CurrentValue) = target.TryExchange( (c, ctx) => c.Bravo < c.Alpha ? new DummyImmutableVal(c.Alpha, c.Bravo + ctx) : new DummyImmutableVal(c.Alpha + ctx, c.Bravo), 1, curValue); if (wasSet) { AssertAreEqual(curValue, prevValue); AssertAreEqual(prevValue.Bravo < prevValue.Alpha ? new DummyImmutableVal(prevValue.Alpha, prevValue.Bravo + 1) : new DummyImmutableVal(prevValue.Alpha + 1, prevValue.Bravo), CurrentValue); } else { AssertAreNotEqual(curValue, prevValue); } }, NumIterations ); // (Func<T, TContext, T>, Func<T, T, bool>) runner.AllThreadsTearDown = target => { AssertAreEqual(NumIterations, target.Value.Alpha); AssertAreEqual(-1 * NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var(wasSet, prevValue, CurrentValue) = target.TryExchange((c, ctx) => new DummyImmutableVal(c.Alpha + ctx, c.Bravo - ctx), 1, (c, n) => c.Alpha + 1 == n.Alpha && c.Bravo - 1 == n.Bravo && c.Alpha < NumIterations); if (wasSet) { AssertAreEqual(new DummyImmutableVal(prevValue.Alpha + 1, prevValue.Bravo - 1), CurrentValue); AssertTrue(CurrentValue.Alpha <= NumIterations); } else { AssertAreEqual(CurrentValue, prevValue); } } } ); runner.AllThreadsTearDown = null; // (Func<T, T>, Func<T, T, TContext, bool>) runner.AllThreadsTearDown = target => { AssertAreEqual(NumIterations, target.Value.Alpha); AssertAreEqual(-1 * NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var(wasSet, prevValue, CurrentValue) = target.TryExchange(c => new DummyImmutableVal(c.Alpha + 1, c.Bravo - 1), (c, n, ctx) => c.Alpha + ctx == n.Alpha && c.Bravo - ctx == n.Bravo && c.Alpha < NumIterations, 1); if (wasSet) { AssertAreEqual(new DummyImmutableVal(prevValue.Alpha + 1, prevValue.Bravo - 1), CurrentValue); AssertTrue(CurrentValue.Alpha <= NumIterations); } else { AssertAreEqual(CurrentValue, prevValue); } } } ); runner.AllThreadsTearDown = null; // (Func<T, TMapContext, T>, Func<T, T, TPredicateContext, bool>) runner.AllThreadsTearDown = target => { AssertAreEqual(NumIterations, target.Value.Alpha); AssertAreEqual(-1 * NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var(wasSet, prevValue, CurrentValue) = target.TryExchange((c, ctx) => new DummyImmutableVal(c.Alpha + ctx, c.Bravo - ctx), 1, (c, n, ctx) => c.Alpha + 1 == n.Alpha && c.Bravo - 1 == n.Bravo && c.Alpha < ctx, NumIterations); if (wasSet) { AssertAreEqual(new DummyImmutableVal(prevValue.Alpha + 1, prevValue.Bravo - 1), CurrentValue); AssertTrue(CurrentValue.Alpha <= NumIterations); } else { AssertAreEqual(CurrentValue, prevValue); } } } ); runner.AllThreadsTearDown = null; }
public void Exchange() { const int NumIterations = 300_000; var atomicIntA = new AtomicInt(0); var atomicIntB = new AtomicInt(0); var runner = NewRunner(new DummyImmutableVal(0, 0)); // (T) runner.GlobalSetUp = (_, __) => { atomicIntA.Set(0); atomicIntB.Set(0); }; runner.AllThreadsTearDown = target => { AssertAreEqual(NumIterations, target.Value.Alpha); AssertAreEqual(NumIterations, target.Value.Bravo); }; runner.ExecuteContinuousSingleWriterCoherencyTests( target => { var newA = atomicIntA.Increment().CurrentValue; var newB = atomicIntB.Increment().CurrentValue; var newValue = new DummyImmutableVal(newA, newB); var prev = target.Exchange(newValue).PreviousValue; AssertAreEqual(prev.Alpha, newA - 1); AssertAreEqual(prev.Bravo, newB - 1); }, NumIterations, target => target.Value, (prev, cur) => { AssertTrue(prev.Alpha <= cur.Alpha); AssertTrue(prev.Bravo <= cur.Bravo); } ); runner.GlobalSetUp = null; runner.AllThreadsTearDown = null; // (Func<T, T>) runner.AllThreadsTearDown = target => { AssertAreEqual(NumIterations, target.Value.Alpha); AssertAreEqual(NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { var exchRes = target.Exchange(t => new DummyImmutableVal(t.Alpha + 1, t.Bravo + 1)); AssertAreEqual(exchRes.PreviousValue.Alpha + 1, exchRes.CurrentValue.Alpha); AssertAreEqual(exchRes.PreviousValue.Bravo + 1, exchRes.CurrentValue.Bravo); }, NumIterations ); runner.AllThreadsTearDown = null; // (Func<T, TContext, T>) runner.AllThreadsTearDown = target => { AssertAreEqual(NumIterations, target.Value.Alpha); AssertAreEqual(NumIterations * 2, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { var exchRes = target.Exchange((t, ctx) => new DummyImmutableVal(t.Alpha + 1, t.Bravo + ctx), 2); AssertAreEqual(exchRes.PreviousValue.Alpha + 1, exchRes.CurrentValue.Alpha); AssertAreEqual(exchRes.PreviousValue.Bravo + 2, exchRes.CurrentValue.Bravo); }, NumIterations ); runner.AllThreadsTearDown = null; }
public void TryExchangeWithoutContext() { const int NumIterations = 200_000; var runner = NewRunner(new DummyImmutableVal(0, 0)); // (T, T) runner.ExecuteContinuousCoherencyTests( target => { var curValue = target.Value; var newValue = new DummyImmutableVal(0, curValue.Bravo + 1); target.TryExchange(newValue, curValue); }, NumIterations, target => target.Value, (prev, cur) => FastAssertTrue(cur.Bravo >= prev.Bravo) ); // (T, Func<T, T, bool>) runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.Alpha); FastAssertEqual(-1 * NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var newValue = new DummyImmutableVal(curValue.Alpha + 1, curValue.Bravo - 1); var(wasSet, prevValue, setValue) = target.TryExchange(newValue, (c, n) => c.Alpha + 1 == n.Alpha && c.Bravo - 1 == n.Bravo); if (wasSet) { FastAssertEqual <DummyImmutableVal>(curValue, prevValue); FastAssertEqual <DummyImmutableVal>(newValue, setValue); } else { FastAssertNotEqual <DummyImmutableVal>(curValue, prevValue); AssertAreEqual(setValue, prevValue); } } } ); runner.AllThreadsTearDown = null; // (Func<T, T>, T) runner.ExecuteFreeThreadedTests( target => { var curValue = target.Value; var(wasSet, prevValue, CurrentValue) = target.TryExchange( c => c.Bravo < c.Alpha ? new DummyImmutableVal(c.Alpha, c.Bravo + 1) : new DummyImmutableVal(c.Alpha + 1, c.Bravo), curValue ); if (wasSet) { FastAssertEqual <DummyImmutableVal>(curValue, prevValue); FastAssertEqual <DummyImmutableVal>(prevValue.Bravo < prevValue.Alpha ? new DummyImmutableVal(prevValue.Alpha, prevValue.Bravo + 1) : new DummyImmutableVal(prevValue.Alpha + 1, prevValue.Bravo), CurrentValue); } else { FastAssertNotEqual <DummyImmutableVal>(curValue, prevValue); } }, NumIterations ); // (Func<T, T>, Func<T, T, bool>) runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.Alpha); FastAssertEqual(-1 * NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var(wasSet, prevValue, CurrentValue) = target.TryExchange(c => new DummyImmutableVal(c.Alpha + 1, c.Bravo - 1), (c, n) => c.Alpha + 1 == n.Alpha && c.Bravo - 1 == n.Bravo && c.Alpha < NumIterations); if (wasSet) { FastAssertEqual <DummyImmutableVal>(new DummyImmutableVal(prevValue.Alpha + 1, prevValue.Bravo - 1), CurrentValue); FastAssertTrue(CurrentValue.Alpha <= NumIterations); } else { AssertAreEqual(prevValue, CurrentValue); } } } ); runner.AllThreadsTearDown = null; }
public void Assert_Coherency_TrySet() { const int NumIterations = 1_000_000; var runner = NewRunner(new DummyImmutableVal(0, 0)); runner.GlobalSetUp = (target, _) => target.Set(new DummyImmutableVal(0, 0)); // bool TrySet(T newValue, Func<T, bool> setPredicate); runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.Alpha); FastAssertEqual(-NumIterations, target.Value.Bravo); }; runner.ExecuteContinuousCoherencyTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var newValue = new DummyImmutableVal(curValue.Alpha + 1, curValue.Bravo - 1); target.TrySet(newValue, v => v.Alpha + 1 == newValue.Alpha && v.Bravo - 1 == newValue.Bravo); FastAssertTrue(target.Value.Alpha > curValue.Alpha); FastAssertTrue(target.Value.Bravo < curValue.Alpha); } }, target => target.Value, (prev, cur) => { FastAssertTrue(cur.Alpha >= prev.Alpha); FastAssertTrue(cur.Bravo <= prev.Bravo); }, v => v.Alpha == NumIterations ); runner.AllThreadsTearDown = null; // bool TrySet(T newValue, Func<T, bool> setPredicate, out T previousValue); runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.Alpha); FastAssertEqual(-NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var newValue = new DummyImmutableVal(curValue.Alpha + 1, curValue.Bravo - 1); var wasSet = target.TrySet(newValue, v => v.Alpha + 1 == newValue.Alpha && v.Bravo - 1 == newValue.Bravo, out var prevValue); if (wasSet) { FastAssertEqual(curValue, prevValue); } else { FastAssertNotEqual(curValue, prevValue); } } } ); runner.AllThreadsTearDown = null; // bool TrySet(Func<T, T> valueMapFunc, Func<T, bool> setPredicate); runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.Alpha); FastAssertEqual(-NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } target.TrySet(v => new DummyImmutableVal(v.Alpha + 1, v.Bravo - 1), v => v == curValue); FastAssertTrue(target.Value.Alpha > curValue.Alpha); FastAssertTrue(target.Value.Bravo < curValue.Alpha); } } ); runner.AllThreadsTearDown = null; // bool TrySet(Func<T, T> valueMapFunc, Func<T, bool> setPredicate, out T previousValue); runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.Alpha); FastAssertEqual(-NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var wasSet = target.TrySet(v => new DummyImmutableVal(v.Alpha + 1, v.Bravo - 1), v => v == curValue, out var prevValue); if (wasSet) { FastAssertEqual(curValue, prevValue); } else { FastAssertNotEqual(curValue, prevValue); } } } ); runner.AllThreadsTearDown = null; // bool TrySet(Func<T, T> valueMapFunc, Func<T, bool> setPredicate, out T previousValue, out T newValue); runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.Alpha); FastAssertEqual(-NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var wasSet = target.TrySet(v => new DummyImmutableVal(v.Alpha + 1, v.Bravo - 1), v => v == curValue, out var prevValue, out var newValue); if (wasSet) { FastAssertEqual(curValue, prevValue); FastAssertEqual(prevValue.Alpha + 1, newValue.Alpha); FastAssertEqual(prevValue.Bravo - 1, newValue.Bravo); } else { FastAssertNotEqual(curValue, prevValue); FastAssertEqual(prevValue, newValue); } } } ); runner.AllThreadsTearDown = null; // bool TrySet(Func<T, T> valueMapFunc, Func<T, T, bool> setPredicate); runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.Alpha); FastAssertEqual(-NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } target.TrySet(v => new DummyImmutableVal(v.Alpha + 1, v.Bravo - 1), (c, n) => c.Alpha == curValue.Alpha && n.Bravo == c.Bravo + 1); FastAssertTrue(target.Value.Alpha > curValue.Alpha); FastAssertTrue(target.Value.Bravo < curValue.Alpha); } } ); runner.AllThreadsTearDown = null; // bool TrySet(Func<T, T> valueMapFunc, Func<T, T, bool> setPredicate, out T previousValue); runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.Alpha); FastAssertEqual(-NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var wasSet = target.TrySet(v => new DummyImmutableVal(v.Alpha + 1, v.Bravo - 1), (c, n) => c.Alpha == curValue.Alpha && n.Bravo == c.Bravo + 1, out var prevValue); if (wasSet) { FastAssertEqual(curValue, prevValue); } else { FastAssertNotEqual(curValue, prevValue); } } } ); runner.AllThreadsTearDown = null; // bool TrySet(Func<T, T> valueMapFunc, Func<T, T, bool> setPredicate, out T previousValue, out T newValue); runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.Alpha); FastAssertEqual(-NumIterations, target.Value.Bravo); }; runner.ExecuteFreeThreadedTests( target => { while (true) { var curValue = target.Value; if (curValue.Alpha == NumIterations) { return; } var wasSet = target.TrySet(v => new DummyImmutableVal(v.Alpha + 1, v.Bravo - 1), (c, n) => c.Alpha == curValue.Alpha && n.Bravo == c.Bravo + 1, out var prevValue, out var newValue); if (wasSet) { FastAssertEqual(curValue, prevValue); FastAssertEqual(prevValue.Alpha + 1, newValue.Alpha); FastAssertEqual(prevValue.Bravo - 1, newValue.Bravo); } else { FastAssertNotEqual(curValue, prevValue); FastAssertEqual(prevValue, newValue); } } } ); runner.AllThreadsTearDown = null; }
protected override bool AreEqual(DummyImmutableVal lhs, DummyImmutableVal rhs) => lhs == rhs;