public void ReentryDictionaryTest() { var concurrentDictionary = new ConcurrentLockDictionary <string>(); for (var iteration = 1; iteration < 50; iteration++) { var testLock = concurrentDictionary.Acquire(ConcurrentLockDictionaryTests.TestLockKey); Assert.AreEqual(expected: iteration, actual: testLock.ReferenceCount); if (iteration == 1) { Monitor.Enter(testLock.LockObject); } else { Assert.IsTrue(Monitor.IsEntered(testLock.LockObject)); } } for (var iteration = 49; iteration > 1; iteration--) { var testLockRemoved = concurrentDictionary.Release(ConcurrentLockDictionaryTests.TestLockKey); Assert.IsFalse(testLockRemoved); } Monitor.Exit(concurrentDictionary[ConcurrentLockDictionaryTests.TestLockKey].LockObject); var finallyRemoved = concurrentDictionary.Release(ConcurrentLockDictionaryTests.TestLockKey); Assert.IsTrue(finallyRemoved); }
public void MultithreadedConcurrencyDictionaryTest() { var concurrentDictionary = new ConcurrentLockDictionary <string>(); var stopWatch = new Stopwatch(); stopWatch.Start(); const int DegreeOfParallelism = 50; const int LockingDurationInMilliseconds = 40; var result = Parallel.For( fromInclusive: 1, toExclusive: 51, body: instanceNumber => { var testLock = concurrentDictionary.Acquire(ConcurrentLockDictionaryTests.TestLockKey); lock (testLock.LockObject) { Thread.Sleep(TimeSpan.FromMilliseconds(LockingDurationInMilliseconds)); } concurrentDictionary.Release(ConcurrentLockDictionaryTests.TestLockKey); }); stopWatch.Stop(); Assert.IsTrue(result.IsCompleted); // NOTE(daviburg): if thread synchronization happened as expected the parallel task will have taken at minimum the duration required for a sequential execution of all the individual locks duration. Assert.IsTrue(stopWatch.Elapsed >= TimeSpan.FromMilliseconds(DegreeOfParallelism * LockingDurationInMilliseconds)); }
public void RemoveNotFoundLockDictionaryTest() { var concurrentDictionary = new ConcurrentLockDictionary <string>(); var testLockRemoved = concurrentDictionary.Release(ConcurrentLockDictionaryTests.TestLockKey); Assert.IsTrue(testLockRemoved); // NOTE(daviburg): Out-of-order release-acquire is harmless, as release adds a dummy zero reference entry if not pre-existing var testLock = concurrentDictionary.Acquire(ConcurrentLockDictionaryTests.TestLockKey); Assert.AreEqual(expected: 1, actual: testLock.ReferenceCount); }
public void SimpleLockDictionaryTest() { var concurrentDictionary = new ConcurrentLockDictionary <string>(); var testLock = concurrentDictionary.Acquire(ConcurrentLockDictionaryTests.TestLockKey); Assert.AreEqual(expected: 1, actual: testLock.ReferenceCount); Assert.IsFalse(Monitor.IsEntered(testLock.LockObject)); Assert.AreSame(expected: testLock.LockObject, actual: concurrentDictionary[ConcurrentLockDictionaryTests.TestLockKey].LockObject); Assert.IsTrue(testLock.Equals(testLock, concurrentDictionary[ConcurrentLockDictionaryTests.TestLockKey])); Assert.AreEqual(expected: testLock.GetHashCode(testLock), actual: concurrentDictionary[ConcurrentLockDictionaryTests.TestLockKey].GetHashCode(concurrentDictionary[ConcurrentLockDictionaryTests.TestLockKey])); var testLockRemoved = concurrentDictionary.Release(ConcurrentLockDictionaryTests.TestLockKey); // NOTE(daviburg): ReferenceLock is a point-in-time copy-on-write class. So the lock we got upon acquire is not changed by the release from the dictionary. Assert.AreEqual(expected: 1, actual: testLock.ReferenceCount); Assert.IsTrue(testLockRemoved); Assert.IsFalse(concurrentDictionary.TryGetValue(ConcurrentLockDictionaryTests.TestLockKey, out ReferencedLock outReferencedLock)); }