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); } } }
public LockableNeedle(T value, LockableContext context) : base(value) { if (ReferenceEquals(context, null)) { throw new ArgumentNullException("context"); } _context = context; _needleLock = new NeedleLock <Thread>(_context.Context); }
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>>(); }
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> >(); }
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); }
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); }
public LockableNeedle(T value, LockableContext context) : base(value) { _context = context ?? throw new ArgumentNullException(nameof(context)); _needleLock = new NeedleLock <Thread>(_context.Context); }