예제 #1
0
        public void WithSingleValueReturns()
        {
            // These vars basically used to ensure the compiler doesn't optimise away the return values entirely
            var longResultVar = 0L;
            var intResultVar  = 0;
            var refResultVar  = "";
            var valResultVar  = 0L;

            for (var i = 0; i < NumIterations; ++i)
            {
                longResultVar += _fastAtomicLong.FastIncrement();
                longResultVar += _fastAtomicLong.FastDecrement();
                longResultVar += _fastAtomicLong.FastExchange(i);

                intResultVar += _fastAtomicInt.FastIncrement();
                intResultVar += _fastAtomicInt.FastDecrement();
                intResultVar += _fastAtomicInt.FastTryExchange(i, i - 1) == i - 1 ? 1 : 0;

                var newUser = new User(i, "Xenoprimate");
                refResultVar = _fastAtomicRef.FastExchange(newUser).Name;
                refResultVar = _fastAtomicRef.FastTryExchange(new User(i * 2, "Ben"), newUser).LoginID == newUser.LoginID ? refResultVar : String.Empty;

                valResultVar += _fastAtomicVal8.FastExchange(new Val8(i)).A;
                valResultVar += _fastAtomicVal16.FastTryExchange(new Val16(i + 1), new Val16(i)).A == i ? 0 : 1;
                valResultVar += _fastAtomicVal32.FastExchange(new Val32(i)).A;
                valResultVar += _fastAtomicVal64.FastTryExchange(new Val64(i + 1), new Val64(i)).A == i ? 0 : 1;

                SimulateContention(ContentionLevel);
            }

            if (longResultVar != 1499996500003L || intResultVar != -728379967 || !refResultVar.Equals("Ben", StringComparison.Ordinal) || valResultVar != 999997000002L)
            {
                throw new ApplicationException("This will never happen; it's just here to force the compiler not to optimise away these vars. These results were measured before.");
            }
        }
예제 #2
0
        public void EquatableFastTryExchange()
        {
            const int NumIterations = 100_000;

            var runner = _equatableRefRunnerFactory.NewRunner(new DummyEquatableRef(0L));

            // Test: Return value of method is always consistent
            runner.ExecuteFreeThreadedTests(
                atomicRef => {
                var curValue  = atomicRef.Value;
                var newValue  = new DummyEquatableRef(curValue.LongProp + 1L);
                var prevValue = atomicRef.FastTryExchange(newValue, curValue);
                var wasSet    = prevValue.Equals(curValue);
                var setValue  = wasSet ? newValue : prevValue;
                if (wasSet)
                {
                    Assert.AreEqual(curValue, prevValue);
                    Assert.AreEqual(newValue, setValue);
                }
                else
                {
                    Assert.AreNotEqual(curValue, prevValue);
                    Assert.AreEqual(setValue, prevValue);
                }
            },
                NumIterations
                );

            // Test: Method does what is expected and is safe from race conditions
            runner.AllThreadsTearDown = atomicRef => Assert.AreEqual(NumIterations, atomicRef.Value.LongProp);
            runner.ExecuteFreeThreadedTests(
                atomicRef => {
                while (true)
                {
                    var curValue = atomicRef.Value;
                    if (curValue.LongProp == NumIterations)
                    {
                        return;
                    }
                    var newValue  = new DummyEquatableRef(curValue.LongProp + 1L);
                    var prevValue = atomicRef.FastTryExchange(newValue, curValue);
                    var wasSet    = prevValue.Equals(curValue);
                    var setValue  = wasSet ? newValue : prevValue;
                    if (wasSet)
                    {
                        Assert.AreEqual(curValue, prevValue);
                        Assert.AreEqual(newValue, setValue);
                    }
                    else
                    {
                        Assert.AreNotEqual(curValue, prevValue);
                        Assert.AreEqual(setValue, prevValue);
                    }
                }
            }
                );
            runner.AllThreadsTearDown = null;

            // Test: Method always exhibits coherency for consecutive reads from external threads
            runner.ExecuteContinuousCoherencyTests(
                atomicRef => {
                var curValue = atomicRef.Value;
                var newValue = new DummyEquatableRef(curValue.LongProp + 1L);
                atomicRef.FastTryExchange(newValue, curValue);
            },
                NumIterations,
                atomicRef => atomicRef.Value,
                (prev, cur) => Assert.True(cur.LongProp >= prev.LongProp)
                );

            // Test: Custom equality is used for types that provide it
            var dummyImmutableA = new DummyImmutableRef("Xenoprimate Rules");
            var dummyImmutableB = new DummyImmutableRef("Xenoprimate Rules");
            var dummyEquatableA = new DummyEquatableRef("Xenoprimate Rules");
            var dummyEquatableB = new DummyEquatableRef("Xenoprimate Rules");
            var atomicImmutable = new AtomicRef <DummyImmutableRef>();
            var atomicEquatable = new AtomicRef <DummyEquatableRef>();

            atomicImmutable.Set(dummyImmutableA);
            atomicImmutable.FastTryExchange(new DummyImmutableRef(), dummyImmutableB);
            Assert.AreEqual(dummyImmutableA, atomicImmutable.Value);
            atomicEquatable.Set(dummyEquatableA);
            var newVal = new DummyEquatableRef();

            atomicEquatable.FastTryExchange(newVal, dummyEquatableB);
            Assert.AreEqual(newVal, atomicEquatable.Value);
        }