public void TestOneReader() { AsyncUpgradeableReaderWriterLock rwLock = new AsyncUpgradeableReaderWriterLock(); using (CancellationTokenSource readLockExit = new CancellationTokenSource()) using (ManualResetEventSlim setWhenReadLockHeld = new ManualResetEventSlim(initialState: false)) { try { Task readLockHold = HoldReadLockAsync(rwLock, setWhenReadLockHeld, readLockExit.Token); setWhenReadLockHeld.Wait(); // 1 reader -> enter reader should not be contended AssertReadLockUncontended(rwLock); // 1 reader -> enter upgradeable should not be contended AssertUpgradeableLockUncontended(rwLock); // 1 reader -> upgrading upgradeable lock should be contended AssertUpgradeableLockUpgradeContended(rwLock); // 1 reader -> enter writer should be contended AssertWriteLockContended(rwLock); } finally { readLockExit.Cancel(); } } }
public void TestUpgradeable() { AsyncUpgradeableReaderWriterLock rwLock = new AsyncUpgradeableReaderWriterLock(); using (CancellationTokenSource upgradeableLockExit = new CancellationTokenSource()) using (ManualResetEventSlim setWhenUpgradeableLockHeld = new ManualResetEventSlim(initialState: false)) { try { Task upgradeableLockHold = HoldUpgradeableLockAsync(rwLock, setWhenUpgradeableLockHeld, upgradeableLockExit.Token); setWhenUpgradeableLockHeld.Wait(); // upgradeable -> enter reader should not be contended AssertReadLockUncontended(rwLock); // upgradeable -> enter upgradeable should be contended AssertUpgradeableLockContended(rwLock); // upgradeable -> enter writer should be contended AssertWriteLockContended(rwLock); // exit upgradeable lock that is in background task upgradeableLockExit.Cancel(); upgradeableLockHold.Wait(); // enter upgradeable lock in foreground and try to upgrade, which should not be contended AssertUpgradeableLockUpgradeUncontended(rwLock); } finally { upgradeableLockExit.Cancel(); } } }
private void AssertWriteLockContended(AsyncUpgradeableReaderWriterLock rwLock) { using (CancellationTokenSource timeout = new CancellationTokenSource(TimeSpan.FromMilliseconds(200))) { Assert.Throws <TaskCanceledException>(() => rwLock.EnterWriteLockAsync(timeout.Token).ConfigureAwait(false).GetAwaiter().GetResult()); } }
private void AssertUpgradeableLockUncontended(AsyncUpgradeableReaderWriterLock rwLock) { using (CancellationTokenSource timeout = new CancellationTokenSource(TimeSpan.FromMilliseconds(200))) using (rwLock.EnterUpgradeableReadLockAsync(timeout.Token).ConfigureAwait(false).GetAwaiter().GetResult()) { ; } }
private void AssertReadLockUncontended(AsyncUpgradeableReaderWriterLock rwLock) { using (CancellationTokenSource timeout = new CancellationTokenSource(TimeSpan.FromMilliseconds(200))) // Will throw an OperationCanceledException if unable to get the lock within 200 ms using (rwLock.EnterReadLockAsync(timeout.Token).ConfigureAwait(false).GetAwaiter().GetResult()) { ; } }
private Task HoldWriteLockAsync(AsyncUpgradeableReaderWriterLock rwLock, ManualResetEventSlim setWhenLockHeld, CancellationToken cancellationToken) { return(Task.Run(() => { using (rwLock.EnterWriteLockAsync(CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult()) { setWhenLockHeld.Set(); cancellationToken.WaitHandle.WaitOne(); } })); }
/// <summary> /// /// </summary> /// <param name="trainingDataLoaderFactory">Must be thread-safe.</param> public RecServiceState(IMalTrainingDataLoaderFactory trainingDataLoaderFactory, MalTrainingData trainingData, IDictionary <int, IList <int> > prereqs) { m_trainingDataLoaderFactory = trainingDataLoaderFactory; JsonRecSourceTypes = GetJsonRecSourceTypes(); m_trainingData = trainingData; m_usernames = GetUsernamesFromTrainingData(m_trainingData); m_animes = m_trainingData.Animes; m_prereqs = prereqs; m_trainingDataLockAsync = new AsyncUpgradeableReaderWriterLock(); m_recSourcesLockAsync = new AsyncUpgradeableReaderWriterLock(); m_pendingRecSourcesLockAsync = new AsyncUpgradeableReaderWriterLock(); }
public void TestEmptyState() { AsyncUpgradeableReaderWriterLock rwLock = new AsyncUpgradeableReaderWriterLock(); // No readers/writers -> enter reader should not be contended AssertReadLockUncontended(rwLock); // No readers/writers -> enter upgradeable and upgrading should not be contended AssertUpgradeableLockUncontended(rwLock); AssertUpgradeableLockUpgradeUncontended(rwLock); // No readers/writers -> enter writer should not be contended AssertWriteLockUncontended(rwLock); }