public void ExitUpgradeableReadLock()
        {
            RuntimeHelpers.PrepareConstrainedRegions();
            try {}
            finally {
                ThreadLockState ctstate = CurrentThreadState;

                if (!ctstate.LockState.Has(LockState.Upgradable | LockState.Read))
                {
                    throw new SynchronizationLockException("The current thread has not entered the lock in upgradable mode");
                }

                if (--ctstate.UpgradeableRecursiveCount == 0)
                {
                    upgradableTaken.Value = false;
                    upgradableEvent.Set();

                    ctstate.LockState &= ~LockState.Upgradable;
                    if (Interlocked.Add(ref rwlock, -RwRead) >> RwReadBit == 0)
                    {
                        readerDoneEvent.Set();
                    }
                }
            }
        }
        public void ExitWriteLock()
        {
            RuntimeHelpers.PrepareConstrainedRegions();
            try {}
            finally {
                ThreadLockState ctstate = CurrentThreadState;

                if (!ctstate.LockState.Has(LockState.Write))
                {
                    throw new SynchronizationLockException("The current thread has not entered the lock in write mode");
                }

                if (--ctstate.WriterRecursiveCount == 0)
                {
                    bool isUpgradable = ctstate.LockState.Has(LockState.Upgradable);
                    ctstate.LockState ^= LockState.Write;

                    int value = Interlocked.Add(ref rwlock, isUpgradable ? RwRead - RwWrite : -RwWrite);
                    writerDoneEvent.Set();
                    if (isUpgradable && value >> RwReadBit == 1)
                    {
                        readerDoneEvent.Reset();
                    }
                }
            }
        }
Exemple #3
0
        bool CheckState(ThreadLockState state, int millisecondsTimeout, LockState validState)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("ReaderWriterLockSlim");
            }

            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("millisecondsTimeout");
            }

            // Detect and prevent recursion
            LockState ctstate = state.LockState;

            if (ctstate != LockState.None && noRecursion && (ctstate != LockState.Upgradable || validState == LockState.Upgradable))
            {
                throw new LockRecursionException("The current thread has already a lock and recursion isn't supported");
            }

            if (noRecursion)
            {
                return(false);
            }

            // If we already had right lock state, just return
            if (ctstate.Has(validState))
            {
                return(true);
            }

            CheckRecursionAuthorization(ctstate, validState);

            return(false);
        }
        private ThreadLockState GetGlobalThreadState()
        {
            var currentThreadState = TypeHelper.LazyCreateNew(ref _currentThreadState);

            if (!currentThreadState.TryGetValue(_id, out var state))
            {
                currentThreadState[_id] = state = new ThreadLockState();
            }

            return(state);
        }
        private ThreadLockState GetGlobalThreadState()
        {
            if (_currentThreadState == null)
            {
                Interlocked.CompareExchange(ref _currentThreadState, new Dictionary <int, ThreadLockState>(), null);
            }

            if (!_currentThreadState.TryGetValue(_id, out var state))
            {
                _currentThreadState[_id] = state = new ThreadLockState();
            }

            return(state);
        }
Exemple #6
0
        //
        // Taking the Upgradable read lock is like taking a read lock
        // but we limit it to a single upgradable at a time.
        //
        public bool TryEnterUpgradeableReadLock(int millisecondsTimeout)
        {
            ThreadLockState ctstate = CurrentThreadState;

            if (CheckState(ctstate, millisecondsTimeout, LockState.Upgradable))
            {
                ++ctstate.UpgradeableRecursiveCount;
                return(true);
            }

            if (ctstate.LockState.Has(LockState.Read))
            {
                throw new LockRecursionException("The current thread has already entered read mode");
            }

            ++numUpgradeWaiters;
            long start = millisecondsTimeout == -1 ? 0 : sw.ElapsedMilliseconds;

            // We first try to obtain the upgradeable right
            while (!upgradableEvent.IsSet() || !upgradableTaken.TryRelaxedSet())
            {
                if (millisecondsTimeout != -1 && (sw.ElapsedMilliseconds - start) > millisecondsTimeout)
                {
                    --numUpgradeWaiters;
                    return(false);
                }

                upgradableEvent.Wait(ComputeTimeout(millisecondsTimeout, start));
            }

            upgradableEvent.Reset();

            // Then it's a simple reader lock acquiring
            if (TryEnterReadLock(ComputeTimeout(millisecondsTimeout, start)))
            {
                ctstate.LockState = LockState.Upgradable;
                --numUpgradeWaiters;
                --ctstate.ReaderRecursiveCount;
                ++ctstate.UpgradeableRecursiveCount;
                return(true);
            }

            upgradableTaken.Value = false;
            upgradableEvent.Set();

            --numUpgradeWaiters;

            return(false);
        }
        ThreadLockState GetGlobalThreadState(int tid)
        {
            if (currentThreadState == null)
            {
                Interlocked.CompareExchange(ref currentThreadState, new Dictionary <int, ThreadLockState> (), null);
            }

            ThreadLockState state;

            if (!currentThreadState.TryGetValue(id, out state))
            {
                currentThreadState [id] = state = new ThreadLockState();
            }

            return(state);
        }
Exemple #8
0
        public void ExitReadLock()
        {
            ThreadLockState ctstate = CurrentThreadState;

            if (!ctstate.LockState.Has(LockState.Read))
            {
                throw new SynchronizationLockException("The current thread has not entered the lock in read mode");
            }

            ctstate.LockState ^= LockState.Read;
            --ctstate.ReaderRecursiveCount;
            if (Interlocked.Add(ref rwlock, -RwRead) >> RwReadBit == 0)
            {
                readerDoneEvent.Set();
            }
        }
Exemple #9
0
        public void ExitUpgradeableReadLock()
        {
            ThreadLockState ctstate = CurrentThreadState;

            if (!ctstate.LockState.Has(LockState.Upgradable | LockState.Read))
            {
                throw new SynchronizationLockException("The current thread has not entered the lock in upgradable mode");
            }

            upgradableTaken.Value = false;
            upgradableEvent.Set();

            ctstate.LockState ^= LockState.Upgradable;
            --ctstate.UpgradeableRecursiveCount;
            if (Interlocked.Add(ref rwlock, -RwRead) >> RwReadBit == 0)
            {
                readerDoneEvent.Set();
            }
        }
        private bool CheckState(ThreadLockState state, int millisecondsTimeout, LockState validState)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(nameof(ReaderWriterLockSlim));
            }

            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout));
            }

            // Detect and prevent recursion
            var stateLockState = state.LockState;

            if (stateLockState != LockState.None && _noRecursion && (!stateLockState.Has(LockState.Upgradable) || validState == LockState.Upgradable))
            {
                throw new LockRecursionException("The current thread has already a lock and recursion isn't supported");
            }

            if (_noRecursion)
            {
                return(false);
            }

            // If we already had right lock state, just return
            if (stateLockState.Has(validState))
            {
                return(true);
            }

            // In read mode you can just enter Read recursively
            if (stateLockState == LockState.Read)
            {
                throw new LockRecursionException();
            }

            return(false);
        }
        public void ExitReadLock()
        {
            RuntimeHelpers.PrepareConstrainedRegions();
            try {}
            finally {
                ThreadLockState ctstate = CurrentThreadState;

                if (!ctstate.LockState.Has(LockState.Read))
                {
                    throw new SynchronizationLockException("The current thread has not entered the lock in read mode");
                }

                if (--ctstate.ReaderRecursiveCount == 0)
                {
                    ctstate.LockState ^= LockState.Read;
                    if (Interlocked.Add(ref rwlock, -RwRead) >> RwReadBit == 0)
                    {
                        readerDoneEvent.Set();
                    }
                }
            }
        }
Exemple #12
0
        public void ExitWriteLock()
        {
            ThreadLockState ctstate = CurrentThreadState;

            if (!ctstate.LockState.Has(LockState.Write))
            {
                throw new SynchronizationLockException("The current thread has not entered the lock in write mode");
            }

            bool isUpgradable = ctstate.LockState.Has(LockState.Upgradable);

            ctstate.LockState ^= LockState.Write;
            --ctstate.WriterRecursiveCount;

            int value = Interlocked.Add(ref rwlock, isUpgradable ? RwRead - RwWrite : -RwWrite);

            writerDoneEvent.Set();
            if (isUpgradable && value >> RwReadBit == 1)
            {
                readerDoneEvent.Reset();
            }
        }
        ThreadLockState GetGlobalThreadState(int tid)
        {
            if (currentThreadState == null)
                Interlocked.CompareExchange(ref currentThreadState, new Dictionary<int, ThreadLockState>(), null);

            ThreadLockState state;
            if (!currentThreadState.TryGetValue(id, out state))
                currentThreadState[id] = state = new ThreadLockState();

            return state;
        }
		bool CheckState (int millisecondsTimeout, ThreadLockState validState)
		{
			if (disposed)
				throw new ObjectDisposedException ("ReaderWriterLockSlim");

			if (millisecondsTimeout < Timeout.Infinite)
				throw new ArgumentOutOfRangeException ("millisecondsTimeout");

			// Detect and prevent recursion
			ThreadLockState ctstate = CurrentThreadState;

			if (recursionPolicy == LockRecursionPolicy.NoRecursion)
				if ((ctstate != ThreadLockState.None && ctstate != ThreadLockState.Upgradable)
				    || (ctstate == ThreadLockState.Upgradable && validState == ThreadLockState.Upgradable))
					throw new LockRecursionException ("The current thread has already a lock and recursion isn't supported");

			// If we already had right lock state, just return
			if (ctstate == validState)
				return true;

			CheckRecursionAuthorization (ctstate, validState);

			return false;
		}
        //
        // Taking the Upgradable read lock is like taking a read lock
        // but we limit it to a single upgradable at a time.
        //
        public bool TryEnterUpgradeableReadLock(int millisecondsTimeout)
        {
            ThreadLockState ctstate = CurrentThreadState;

            if (CheckState(ctstate, millisecondsTimeout, LockState.Upgradable))
            {
                ++ctstate.UpgradeableRecursiveCount;
                return(true);
            }

            if (ctstate.LockState.Has(LockState.Read))
            {
                throw new LockRecursionException("The current thread has already entered read mode");
            }

            ++numUpgradeWaiters;
            long start   = millisecondsTimeout == -1 ? 0 : sw.ElapsedMilliseconds;
            bool taken   = false;
            bool success = false;

            // We first try to obtain the upgradeable right
            try {
                while (!upgradableEvent.IsSet() || !taken)
                {
                    try {}
                    finally {
                        taken = upgradableTaken.TryRelaxedSet();
                    }
                    if (taken)
                    {
                        break;
                    }
                    if (millisecondsTimeout != -1 && (sw.ElapsedMilliseconds - start) > millisecondsTimeout)
                    {
                        --numUpgradeWaiters;
                        return(false);
                    }

                    upgradableEvent.Wait(ComputeTimeout(millisecondsTimeout, start));
                }

                upgradableEvent.Reset();

                RuntimeHelpers.PrepareConstrainedRegions();
                try {
                    // Then it's a simple reader lock acquiring
                    TryEnterReadLock(ComputeTimeout(millisecondsTimeout, start), ref success);
                } finally {
                    if (success)
                    {
                        ctstate.LockState |= LockState.Upgradable;
                        ctstate.LockState &= ~LockState.Read;
                        --ctstate.ReaderRecursiveCount;
                        ++ctstate.UpgradeableRecursiveCount;
                    }
                    else
                    {
                        upgradableTaken.Value = false;
                        upgradableEvent.Set();
                    }
                }

                --numUpgradeWaiters;
            } catch {
                // An async exception occured, if we had taken the upgradable mode, release it
                if (taken && !success)
                {
                    upgradableTaken.Value = false;
                }
            }

            return(success);
        }
		static void CheckRecursionAuthorization (ThreadLockState ctstate, ThreadLockState desiredState)
		{
			// In read mode you can just enter Read recursively
			if (ctstate == ThreadLockState.Read)
				throw new LockRecursionException ();				
		}
        public bool TryEnterWriteLock(int millisecondsTimeout)
        {
            ThreadLockState ctstate = CurrentThreadState;

            if (CheckState(ctstate, millisecondsTimeout, LockState.Write))
            {
                ++ctstate.WriterRecursiveCount;
                return(true);
            }

            ++numWriteWaiters;
            bool isUpgradable = ctstate.LockState.Has(LockState.Upgradable);
            bool registered   = false;
            bool success      = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                /* If the code goes there that means we had a read lock beforehand
                 * that need to be suppressed, we also take the opportunity to register
                 * our interest in the write lock to avoid other write wannabe process
                 * coming in the middle
                 */
                if (isUpgradable && rwlock >= RwRead)
                {
                    try {}
                    finally {
                        if (Interlocked.Add(ref rwlock, RwWaitUpgrade - RwRead) >> RwReadBit == 0)
                        {
                            readerDoneEvent.Set();
                        }
                        registered = true;
                    }
                }

                int  stateCheck   = isUpgradable ? RwWaitUpgrade + RwWait : RwWait;
                long start        = millisecondsTimeout == -1 ? 0 : sw.ElapsedMilliseconds;
                int  registration = isUpgradable ? RwWaitUpgrade : RwWait;

                do
                {
                    int state = rwlock;

                    if (state <= stateCheck)
                    {
                        try {}
                        finally {
                            var toWrite = state + RwWrite - (registered ? registration : 0);
                            if (Interlocked.CompareExchange(ref rwlock, toWrite, state) == state)
                            {
                                writerDoneEvent.Reset();
                                ctstate.LockState ^= LockState.Write;
                                ++ctstate.WriterRecursiveCount;
                                --numWriteWaiters;
                                registered = false;
                                success    = true;
                            }
                        }
                        if (success)
                        {
                            return(true);
                        }
                    }

                    state = rwlock;

                    // We register our interest in taking the Write lock (if upgradeable it's already done)
                    if (!isUpgradable)
                    {
                        while ((state & RwWait) == 0)
                        {
                            try {}
                            finally {
                                if (Interlocked.CompareExchange(ref rwlock, state | RwWait, state) == state)
                                {
                                    registered = true;
                                }
                            }
                            if (registered)
                            {
                                break;
                            }
                            state = rwlock;
                        }
                    }

                    // Before falling to sleep
                    do
                    {
                        if (rwlock <= stateCheck)
                        {
                            break;
                        }
                        if ((rwlock & RwWrite) != 0)
                        {
                            writerDoneEvent.Wait(ComputeTimeout(millisecondsTimeout, start));
                        }
                        else if ((rwlock >> RwReadBit) > 0)
                        {
                            readerDoneEvent.Wait(ComputeTimeout(millisecondsTimeout, start));
                        }
                    } while (millisecondsTimeout < 0 || (sw.ElapsedMilliseconds - start) < millisecondsTimeout);
                } while (millisecondsTimeout < 0 || (sw.ElapsedMilliseconds - start) < millisecondsTimeout);

                --numWriteWaiters;
            } finally {
                if (registered)
                {
                    Interlocked.Add(ref rwlock, isUpgradable ? -RwWaitUpgrade : -RwWait);
                }
            }

            return(false);
        }
        bool TryEnterReadLock(int millisecondsTimeout, ref bool success)
        {
            ThreadLockState ctstate = CurrentThreadState;

            if (CheckState(ctstate, millisecondsTimeout, LockState.Read))
            {
                ++ctstate.ReaderRecursiveCount;
                return(true);
            }

            // This is downgrading from upgradable, no need for check since
            // we already have a sort-of read lock that's going to disappear
            // after user calls ExitUpgradeableReadLock.
            // Same idea when recursion is allowed and a write thread wants to
            // go for a Read too.
            if (ctstate.LockState.Has(LockState.Upgradable) ||
                (!noRecursion && ctstate.LockState.Has(LockState.Write)))
            {
                RuntimeHelpers.PrepareConstrainedRegions();
                try {}
                finally {
                    Interlocked.Add(ref rwlock, RwRead);
                    ctstate.LockState |= LockState.Read;
                    ++ctstate.ReaderRecursiveCount;
                    success = true;
                }

                return(true);
            }

            ++numReadWaiters;
            int  val   = 0;
            long start = millisecondsTimeout == -1 ? 0 : sw.ElapsedMilliseconds;

            do
            {
                /* Check if a writer is present (RwWrite) or if there is someone waiting to
                 * acquire a writer lock in the queue (RwWait | RwWaitUpgrade).
                 */
                if ((rwlock & (RwWrite | RwWait | RwWaitUpgrade)) > 0)
                {
                    writerDoneEvent.Wait(ComputeTimeout(millisecondsTimeout, start));
                    continue;
                }

                /* Optimistically try to add ourselves to the reader value
                 * if the adding was too late and another writer came in between
                 * we revert the operation.
                 */
                RuntimeHelpers.PrepareConstrainedRegions();
                try {}
                finally {
                    if (((val = Interlocked.Add(ref rwlock, RwRead)) & (RwWrite | RwWait | RwWaitUpgrade)) == 0)
                    {
                        /* If we are the first reader, reset the event to let other threads
                         * sleep correctly if they try to acquire write lock
                         */
                        if (val >> RwReadBit == 1)
                        {
                            readerDoneEvent.Reset();
                        }

                        ctstate.LockState ^= LockState.Read;
                        ++ctstate.ReaderRecursiveCount;
                        --numReadWaiters;
                        success = true;
                    }
                    else
                    {
                        Interlocked.Add(ref rwlock, -RwRead);
                    }
                }
                if (success)
                {
                    return(true);
                }

                writerDoneEvent.Wait(ComputeTimeout(millisecondsTimeout, start));
            } while (millisecondsTimeout == -1 || (sw.ElapsedMilliseconds - start) < millisecondsTimeout);

            --numReadWaiters;
            return(false);
        }
        bool CheckState(ThreadLockState state, int millisecondsTimeout, LockState validState)
        {
            if (disposed)
                throw new ObjectDisposedException("ReaderWriterLockSlim");

            if (millisecondsTimeout < -1)
                throw new ArgumentOutOfRangeException("millisecondsTimeout");

            // Detect and prevent recursion
            LockState ctstate = state.LockState;

            if (ctstate != LockState.None && noRecursion && (!ctstate.Has(LockState.Upgradable) || validState == LockState.Upgradable))
                throw new LockRecursionException("The current thread has already a lock and recursion isn't supported");

            if (noRecursion)
                return false;

            // If we already had right lock state, just return
            if (ctstate.Has(validState))
                return true;

            // In read mode you can just enter Read recursively
            if (ctstate == LockState.Read)
                throw new LockRecursionException();

            return false;
        }
		internal static bool Has (this ThreadLockState state, ThreadLockState value)
		{
			return (state & value) > 0;
		}