Esempio n. 1
0
        public void EquatableMappedTryExchange()
        {
            const int NumIterations = 100_000;

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

            // Test: Return value of method is always consistent
            equatableRunner.ExecuteFreeThreadedTests(
                atomicRef => {
                var curValue = atomicRef.Value;
                var(wasSet, prevValue, CurrentValue) = atomicRef.TryExchange(c => new DummyEquatableRef(c.LongProp + 1L), curValue);
                if (wasSet)
                {
                    Assert.AreEqual(curValue, prevValue);
                    Assert.AreEqual(new DummyEquatableRef(prevValue.LongProp + 1L), CurrentValue);
                }
                else
                {
                    Assert.AreNotEqual(curValue, prevValue);
                }
            },
                NumIterations
                );

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

            // Test: Method always exhibits coherency for consecutive reads from external threads
            equatableRunner.ExecuteContinuousCoherencyTests(
                atomicRef => {
                var curValue = atomicRef.Value;
                atomicRef.TryExchange(c => new DummyEquatableRef(c.LongProp + 1L), 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);
            Assert.AreEqual(false, atomicImmutable.TryExchange(c => new DummyImmutableRef(), dummyImmutableB).ValueWasSet);
            atomicEquatable.Set(dummyEquatableA);
            Assert.AreEqual(true, atomicEquatable.TryExchange(c => new DummyEquatableRef(), dummyEquatableB).ValueWasSet);
        }
Esempio n. 2
0
        public void FastTryExchangeRefOnly()
        {
            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.FastTryExchangeRefOnly(newValue, curValue);
                var wasSet    = ReferenceEquals(prevValue, curValue);
                var setValue  = wasSet ? newValue : prevValue;
                if (wasSet)
                {
                    Assert.True(ReferenceEquals(curValue, prevValue));
                    Assert.True(ReferenceEquals(newValue, setValue));
                }
                else
                {
                    Assert.False(ReferenceEquals(curValue, prevValue));
                    Assert.True(ReferenceEquals(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.FastTryExchangeRefOnly(newValue, curValue);
                    var wasSet    = ReferenceEquals(prevValue, curValue);
                    var setValue  = wasSet ? newValue : prevValue;
                    if (wasSet)
                    {
                        Assert.True(ReferenceEquals(curValue, prevValue));
                        Assert.True(ReferenceEquals(newValue, setValue));
                    }
                    else
                    {
                        Assert.False(ReferenceEquals(curValue, prevValue));
                        Assert.True(ReferenceEquals(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.FastTryExchangeRefOnly(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.FastTryExchangeRefOnly(new DummyImmutableRef(), dummyImmutableB);
            Assert.AreEqual(dummyImmutableA, atomicImmutable.Value);
            atomicEquatable.Set(dummyEquatableA);
            var newVal = new DummyEquatableRef();

            atomicEquatable.FastTryExchangeRefOnly(newVal, dummyEquatableB);
            Assert.AreEqual(dummyEquatableA, atomicEquatable.Value);
        }
Esempio n. 3
0
        public void EquatablePredicatedTryExchange()
        {
            const int NumIterations = 100_000;

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

            // Test: Return value of TryExchange is always consistent
            equatableRunner.ExecuteFreeThreadedTests(
                atomicRef => {
                var curValue = atomicRef.Value;
                var newValue = new DummyEquatableRef(curValue.LongProp + 1L);
                var(wasSet, prevValue, setValue) = atomicRef.TryExchange(newValue, (c, n) => c.LongProp == n.LongProp - 1L);
                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
            equatableRunner.AllThreadsTearDown = atomicRef => Assert.AreEqual(NumIterations, atomicRef.Value.LongProp);
            equatableRunner.ExecuteFreeThreadedTests(
                atomicRef => {
                while (true)
                {
                    var curValue = atomicRef.Value;
                    if (curValue.LongProp == NumIterations)
                    {
                        return;
                    }
                    var newValue = new DummyEquatableRef(curValue.LongProp + 1L);
                    var(wasSet, prevValue, setValue) = atomicRef.TryExchange(newValue, (c, n) => c.LongProp == n.LongProp - 1L);
                    if (wasSet)
                    {
                        Assert.AreEqual(curValue, prevValue);
                        Assert.AreEqual(newValue, setValue);
                    }
                    else
                    {
                        Assert.AreNotEqual(curValue, prevValue);
                        Assert.AreEqual(setValue, prevValue);
                    }
                }
            }
                );
            equatableRunner.AllThreadsTearDown = null;

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