예제 #1
0
        public void Nested()
        {
            var context = new LockableContext(16);
            var needle = new LockableNeedle<int>(5, context);

            Assert.AreEqual(5, needle.Value);
            Assert.Throws<InvalidOperationException>(() => needle.Value = 7);

            using (context.Enter())
            {
                Assert.DoesNotThrow(() => needle.Value = 7);
                Assert.AreEqual(7, needle.Value);
                using (context.Enter())
                {
                    // You can recapture
                    Assert.DoesNotThrow(() => needle.Value = 9);
                    Assert.AreEqual(9, needle.Value);
                }
                using (context.Enter())
                {
                    // There is no need to recapture
                    Assert.DoesNotThrow(() => needle.Value = 11);
                    Assert.AreEqual(11, needle.Value);
                }
            }
        }
예제 #2
0
 public LockableNeedle(T value, LockableContext context)
     : base(value)
 {
     if (ReferenceEquals(context, null))
     {
         throw new ArgumentNullException("context");
     }
     _context    = context;
     _needleLock = new NeedleLock <Thread>(_context.Context);
 }
예제 #3
0
 internal LockableSlot(LockableContext context)
 {
     _context = context;
     _parent = _context.Slot;
     _context.Slot = this;
     // --
     LockSlot<Thread> lockSlot = null;
     ThreadingHelper.SpinWaitUntil(() => _context.Context.ClaimSlot(out lockSlot));
     lockSlot.Value = Thread.CurrentThread;
     _lockSlot = lockSlot;
     _needleLocks = new List<NeedleLock<Thread>>();
 }
예제 #4
0
        internal LockableSlot(LockableContext context)
        {
            _context      = context;
            _parent       = _context.Slot;
            _context.Slot = this;
            // --
            LockSlot <Thread> lockSlot = null;

            ThreadingHelper.SpinWaitUntil(() => _context.Context.ClaimSlot(out lockSlot));
            lockSlot.Value = Thread.CurrentThread;
            _lockSlot      = lockSlot;
            _needleLocks   = new List <NeedleLock <Thread> >();
        }
예제 #5
0
        public void SimpleTest()
        {
            var context = new LockableContext(16);
            var needle = new LockableNeedle<int>(5, context);

            Assert.AreEqual(5, needle.Value);
            Assert.Throws<InvalidOperationException>(() => needle.Value = 7);

            using (context.Enter())
            {
                Assert.DoesNotThrow(() => needle.Value = 7);
                Assert.AreEqual(7, needle.Value);
            }

            Assert.Throws<InvalidOperationException>(() => needle.Value = 9);
        }
예제 #6
0
        public void TwoThreadsSet()
        {
            var context = new LockableContext(16);
            var needle = new LockableNeedle<int>(5, context);
            int[] count = {0};

            var info = new CircularBucket<string>(64);

            Assert.AreEqual(5, needle.Value);
            Assert.Throws<InvalidOperationException>(() => needle.Value = 7);

            var threads = new []
            {
                new Thread(() =>
                {
                    using (context.Enter())
                    {
                        try
                        {
                            info.Add("First thread did enter.");
                            var found = needle.Value;
                            info.Add("First thread found: " + found + " will set: " + (found + 2));
                            needle.Value = found + 2;
                            info.Add("First thread set: " + needle.Value);
                            info.Add("First thread set count to: " + Interlocked.Increment(ref count[0]));
                            info.Add("First thread done.");
                        }
                        catch (Exception exc)
                        {
                            info.Add("First thread exception: " + exc.Message);
                            throw;
                        }
                    }
                    info.Add("First thread left.");
                }),
                new Thread(() =>
                {
                    using (context.Enter())
                    {
                        try
                        {
                            info.Add("Second thread did enter.");
                            var found = needle.Value;
                            info.Add("Second thread found: " + found + " will set: " + (found + 3));
                            needle.Value = found + 3;
                            info.Add("Second thread set: " + needle.Value);
                            info.Add("Second thread set count to: " + Interlocked.Increment(ref count[0]));
                            info.Add("Second thread done.");
                        }
                        catch (Exception exc)
                        {
                            info.Add("Second thread exception: " + exc.Message);
                            throw;
                        }
                    }
                    info.Add("Second thread left.");
                })
            };

            threads[0].Start();
            threads[1].Start();
            threads[0].Join();
            threads[1].Join();

            foreach (var item in info)
            {
                Trace.WriteLine(item);
            }

            Trace.WriteLine("Count = " + Thread.VolatileRead(ref count[0]));
            Trace.WriteLine("Found = " + needle.Value);

            Assert.IsTrue(needle.Value == 7 || needle.Value == 8 || needle.Value == 10);
        }
예제 #7
0
 public LockableNeedle(T value, LockableContext context)
     : base(value)
 {
     _context    = context ?? throw new ArgumentNullException(nameof(context));
     _needleLock = new NeedleLock <Thread>(_context.Context);
 }