コード例 #1
0
ファイル: LocksmithTests.cs プロジェクト: Dextarius/Locksmith
        public void Locksmith_WhenReadLockIsUpgradedWithOnlyOneReader_PreventsNewReadersFromEntering()
        {
            const int failureValue  = 25;
            const int expectedValue = 10;
            int       result        = expectedValue;

            Locksmith.EnterReadLock(ref lockState, readLockTestObject);
            Locksmith.Upgrade(ref lockState, writeLockTestObject);
            {
                StartNewThreadThatRuns(SetReadResultToFailureValue);
                Thread.Sleep(1000);
                Assert.That(result, Is.EqualTo(expectedValue));
            }
            Locksmith.ExitWriteLock(ref lockState, readLockTestObject, writeLockTestObject);

            return;


            void SetReadResultToFailureValue()
            {
                Locksmith.EnterReadLock(ref lockState, readLockTestObject);
                result = failureValue;
                Locksmith.ExitReadLock(ref lockState, readLockTestObject, writeLockTestObject);
            }
        }
コード例 #2
0
ファイル: LocksmithTests.cs プロジェクト: Dextarius/Locksmith
        public void Locksmith_WhenReadLockIsUpgraded_ThrowsIfExitReadLockIsCalled()
        {
            Locksmith.EnterReadLock(ref lockState, readLockTestObject);
            Locksmith.Upgrade(ref lockState, writeLockTestObject);
            Assert.Throws <SynchronizationLockException>(TryToCallExitReadLock);
            Locksmith.ExitWriteLock(ref lockState, readLockTestObject, writeLockTestObject);

            return;


            void TryToCallExitReadLock() =>
            Locksmith.ExitReadLock(ref lockState, readLockTestObject, writeLockTestObject);
        }
コード例 #3
0
ファイル: LocksmithTests.cs プロジェクト: Dextarius/Locksmith
        public void Locksmith_WhenReadLockIsUpgradedWhileOtherReadersAreActive_WaitsUntilAllOtherReadersExitToConvertLock()
        {
            const int        numberOfOtherReaders = 10;
            int              numberOfReads        = 0;
            int              numberOfExits        = 0;
            CountdownEvent   readEvent            = new CountdownEvent(numberOfOtherReaders);
            CountdownEvent   exitEvent            = new CountdownEvent(numberOfOtherReaders);
            ManualResetEvent upgradeEvent         = new ManualResetEvent(false);

            Locksmith.EnterReadLock(ref lockState, readLockTestObject);

            for (int i = 0; i < numberOfOtherReaders; i++)
            {
                StartNewThreadThatRuns(IncrementNumReadsInsideReadLock);
            }

            readEvent.Wait();
            Assert.That(numberOfReads, Is.EqualTo(numberOfOtherReaders));
            upgradeEvent.Set();

            Locksmith.Upgrade(ref lockState, writeLockTestObject);
            {
                Assert.That(lockState.IsReadLocked() == false, $"{lockState}");
                exitEvent.Wait();
                Assert.That(numberOfExits, Is.EqualTo(numberOfOtherReaders));
            }
            Locksmith.ExitWriteLock(ref lockState, readLockTestObject, writeLockTestObject);

            return;


            void IncrementNumReadsInsideReadLock()
            {
                Locksmith.EnterReadLock(ref lockState, readLockTestObject);
                {
                    Interlocked.Increment(ref numberOfReads);
                    readEvent.Signal();
                    upgradeEvent.WaitOne();
                    Thread.Sleep(1000);
                    Assert.That(ReservedForUpgrade && IsReadLocked);
                }
                Locksmith.ExitReadLock(ref lockState, readLockTestObject, writeLockTestObject);

                Interlocked.Increment(ref numberOfExits);
                exitEvent.Signal();
            }
        }
コード例 #4
0
        public bool IfValueEqualsFirstSetToSecond(T valueToTestFor, T valueToSetTo)
        {
            Locksmith.EnterReadLock(ref lockState, readLockobject);
            {
                if (lockedValue.Equals(valueToTestFor))
                {
                    Locksmith.Upgrade(ref lockState, this);
                    {
                        lockedValue = valueToSetTo;
                    }
                    Locksmith.ExitWriteLock(ref lockState, readLockobject, this);

                    return(true);
                }
            }
            Locksmith.ExitReadLock(ref lockState, readLockobject, this);

            return(false);
        }
コード例 #5
0
ファイル: LocksmithTests.cs プロジェクト: Dextarius/Locksmith
        public void Locksmith_WhenReadLockIsUpgradedWhileOtherReadersAreActive_PreventsNewReadersFromEntering()
        {
            const int        numberOfOtherReaders   = 10;
            int              numberOfReadersEntered = 0;
            int              numberOfExits          = 0;
            CountdownEvent   readEvent         = new CountdownEvent(numberOfOtherReaders);
            CountdownEvent   exitEvent         = new CountdownEvent(numberOfOtherReaders);
            ManualResetEvent outerUpgradeEvent = new ManualResetEvent(false);
            ManualResetEvent innerUpgradeEvent = new ManualResetEvent(false);

            for (int i = 0; i < numberOfOtherReaders; i++)
            {
                StartNewThreadThatRuns(IncrementNumReadsInsideReadLock_FirstSet);
            }

            readEvent.Wait();
            Assert.That(numberOfReadersEntered, Is.EqualTo(numberOfOtherReaders));
            StartNewThreadThatRuns(EnterReadLockAndUpgrade);
            exitEvent.Wait();

            Assert.That(numberOfExits, Is.EqualTo(numberOfOtherReaders));

            for (int i = 0; i < numberOfOtherReaders; i++)
            {
                StartNewThreadThatRuns(IncrementNumReadsInsideReadLock_SecondSet);
            }

            Thread.Sleep(1000);
            Assert.That(numberOfReadersEntered, Is.EqualTo(numberOfOtherReaders));
            innerUpgradeEvent.Set();

            return;

            void EnterReadLockAndUpgrade()
            {
                Locksmith.EnterReadLock(ref lockState, readLockTestObject);
                outerUpgradeEvent.Set();
                Locksmith.Upgrade(ref lockState, writeLockTestObject);
                {
                    innerUpgradeEvent.WaitOne();
                    Assert.That(numberOfExits, Is.EqualTo(numberOfOtherReaders));
                }
                Locksmith.ExitWriteLock(ref lockState, readLockTestObject, writeLockTestObject);
            }

            void IncrementNumReadsInsideReadLock_FirstSet()
            {
                Locksmith.EnterReadLock(ref lockState, readLockTestObject);
                {
                    Interlocked.Increment(ref numberOfReadersEntered);
                    readEvent.Signal();
                    outerUpgradeEvent.WaitOne();
                    Thread.Sleep(1000);
                }
                Locksmith.ExitReadLock(ref lockState, readLockTestObject, writeLockTestObject);

                Interlocked.Increment(ref numberOfExits);
                exitEvent.Signal();
            }

            void IncrementNumReadsInsideReadLock_SecondSet()
            {
                Locksmith.EnterReadLock(ref lockState, readLockTestObject);
                {
                    Interlocked.Increment(ref numberOfReadersEntered);
                }
                Locksmith.ExitReadLock(ref lockState, readLockTestObject, writeLockTestObject);

                Interlocked.Increment(ref numberOfExits);
            }
        }