Ejemplo n.º 1
0
        public void ConcurrentWriteAndAdviseTest()
        {
            const int threadsCount = 10;

            for (int i = 0; i < 200; i++)
            {
                using var def = new LifetimeDefinition();
                var lifetime = def.Lifetime;

                var prop = new WriteOnceProperty <int>();

                var value1 = new AtomicValue();
                var count  = 0;

                var tasks = Enumerable.Range(0, threadsCount).Select(j => Task.Factory.StartNew(() =>
                {
                    Interlocked.Increment(ref count);
                    SpinWait.SpinUntil(() => Memory.VolatileRead(ref count) == threadsCount); // sync threads

                    if (!prop.SetIfEmpty(j))
                    {
                        return;
                    }

                    if (!value1.SetIfDefault(j))
                    {
                        Assert.Fail("Value must be written once");
                    }
                }, lifetime)).ToArray();

                var values = Enumerable.Range(0, i).Select(j =>
                {
                    var localValue = new AtomicValue();

                    prop.Advise(lifetime, v =>
                    {
                        if (!localValue.SetIfDefault(v))
                        {
                            Assert.Fail("Handled must not be called twice");
                        }
                    });
                    return(localValue);
                }).ToArray();

                Assert.IsTrue(Task.WaitAll(tasks, TimeSpan.FromMinutes(1)), "Task.WaitAll(tasks, TimeSpan.FromMinutes(1))");

                value1.AssertNonDefault();

                if (values.Length != 0)
                {
                    var value = values.Select(x => x.Value).Distinct().Single();
                    Assert.AreEqual(value, value1.Value);
                }

                Assert.AreEqual(value1.Value, prop.Value);

                prop.fireInternal(10000);
            }
        }