Esempio n. 1
0
 public LockContext(int capacity)
 {
     _capacity = NumericHelper.PopulationCount(capacity) == 1 ? capacity : NumericHelper.NextPowerOf2(capacity);
     _slots    = new NeedleBucket <LockSlot <T>, LazyNeedle <LockSlot <T> > >
                 (
         index => new LockSlot <T>
         (
             this,
             index,
             _version.AdvanceNewToken()
         ),
         _capacity
                 );
     _closedSlots = new FixedSizeQueue <LockSlot <T> >(_capacity);
 }
Esempio n. 2
0
        public void TransactionalDataStructure()
        {
            var  info   = new CircularBucket <string>(32);
            var  bucket = new NeedleBucket <int, Transact.Needle <int> >(index => index, value => new Transact.Needle <int>(value), 5);
            var  didA   = false;
            bool didB;

            using (var enteredWorkA = new ManualResetEvent(false))
            {
                using (var enteredWorkB = new ManualResetEvent(false))
                {
                    using (var done = new ManualResetEvent(false))
                    {
                        ManualResetEvent[] handles = { enteredWorkA, enteredWorkB, done };
                        ThreadPool.QueueUserWorkItem
                        (
                            _ =>
                        {
                            info.Add("Work A - start");
                            using (var transact = new Transact())
                            {
                                info.Add("Work A - enter");
                                handles[0].Set();
                                info.Add("Work A - reported, waiting");
                                handles[1].WaitOne();
                                info.Add("Work A - going");
                                // foreach will not trigger the creation of items
                                var got = new int[5];
                                var set = new int[5];
                                for (var index = 0; index < 5; index++)
                                {
                                    got[index] = bucket.GetNeedle(index).Value;
                                    set[index] = got[index] + 1;
                                    bucket.GetNeedle(index).Value = set[index];
                                }
                                info.Add(string.Format("Work A - Got: [{0}, {1}, {2}, {3}, {4}] - Set: [{5}, {6}, {7}, {8}, {9}]", got[0], got[1], got[2], got[3], got[4], set[0], set[1], set[2], set[3], set[4]));
                                if (!bucket.SequenceEqual(set))
                                {
                                    info.Add("Work A - ??");
                                }
                                info.Add("Work A - before commit");
                                didA = transact.Commit();
                                info.Add("Work A - after commit: " + didA);
                                if (didA != bucket.SequenceEqual(set))
                                {
                                    info.Add("Work A - ???");
                                }
                                info.Add("Work A - report");
                                handles[2].Set();
                                info.Add("Work A - done");
                            }
                        }
                        );
                        {
                            info.Add("Work B - start");
                            using (var transact = new Transact())
                            {
                                info.Add("Work B - waiting A to enter");
                                handles[0].WaitOne();
                                info.Add("Work B - telling Work A to go");
                                handles[1].Set();
                                info.Add("Work B - going");
                                // foreach will not trigger the creation of items
                                var got = new int[5];
                                var set = new int[5];
                                for (var index = 0; index < 5; index++)
                                {
                                    got[index] = bucket.GetNeedle(index).Value;
                                    set[index] = got[index] * 2;
                                    bucket.GetNeedle(index).Value = set[index];
                                }
                                info.Add(string.Format("Work B - Got: [{0}, {1}, {2}, {3}, {4}] - Set: [{5}, {6}, {7}, {8}, {9}]", got[0], got[1], got[2], got[3], got[4], set[0], set[1], set[2], set[3], set[4]));
                                if (!bucket.SequenceEqual(set))
                                {
                                    info.Add("Work B - ??");
                                }
                                info.Add("Work B - before commit");
                                didB = transact.Commit();
                                info.Add("Work B - after commit: " + didB);
                                if (didB != bucket.SequenceEqual(set))
                                {
                                    info.Add("Work B - ???");
                                }
                                info.Add("Work B - waiting report");
                                handles[2].WaitOne();
                                info.Add("Work B - done");
                            }
                        }
                        var result = bucket;
                        // These are more likely in debug mode
                        // (+1)
                        if (result.SequenceEqual(new[] { 1, 2, 3, 4, 5 }))
                        {
                            Assert.IsTrue(didA);
                            Assert.IsFalse(didB);
                            return;
                        }
                        // (*2)
                        if (result.SequenceEqual(new[] { 0, 2, 4, 6, 8 }))
                        {
                            Assert.IsFalse(didA);
                            Assert.IsTrue(didB);
                            return;
                        }
                        // This are more likely with optimization enabled
                        // (+1) and then (*2)
                        if (result.SequenceEqual(new[] { 2, 4, 6, 8, 10 }))
                        {
                            Assert.IsTrue(didA);
                            Assert.IsTrue(didB);
                            return;
                        }
                        // (*2) and then (+1)
                        if (result.SequenceEqual(new[] { 1, 3, 5, 7, 9 }))
                        {
                            Assert.IsTrue(didA);
                            Assert.IsTrue(didB);
                            return;
                        }
                        //---
                        if (result.SequenceEqual(new[] { 0, 1, 2, 3, 4 }))
                        {
                            Assert.IsFalse(didA);
                            Assert.IsFalse(didB);
                            return;
                        }
                        var found = result.ToArray();
                        Trace.WriteLine(" --- REPORT --- ");
                        foreach (var msg in info)
                        {
                            Trace.WriteLine(msg);
                        }
                        Assert.Fail("T_T - This is what was found: [{0}, {1}, {2}, {3}, {4}]", found[0], found[1], found[2], found[3], found[4]);
                    }
                }
            }
        }