System.Threading.ReaderWriterLock.AcquireWriterLock C# (CSharp) Method

AcquireWriterLock() public method

public AcquireWriterLock ( int millisecondsTimeout ) : void
millisecondsTimeout int
return void
        public void AcquireWriterLock(int millisecondsTimeout)
        {
            if (millisecondsTimeout < -1)
            {
                throw GetInvalidTimeoutException(nameof(millisecondsTimeout));
            }

            int threadID = GetCurrentThreadID();

            // Check for the fast path
            if (Interlocked.CompareExchange(ref _state, LockStates.Writer, 0) == 0)
            {
                Debug.Assert((_state & LockStates.ReadersMask) == 0);
            }
            // Check if the thread already has writer lock
            else if (_writerID == threadID)
            {
                if (_writerLevel == MaxAcquireCount)
                {
                    throw new OverflowException(SR.Overflow_UInt16);
                }
                ++_writerLevel;
                return;
            }
            else
            {
                int spinCount = 0;
                int currentState = _state;
                do
                {
                    int knownState = currentState;

                    // Writer need not wait if there are no readers and writer
                    if (knownState == 0 || knownState == LockStates.CachingEvents)
                    {
                        // Can be a writer
                        currentState = Interlocked.CompareExchange(ref _state, knownState + LockStates.Writer, knownState);
                        if (currentState == knownState)
                        {
                            // Only writer
                            break;
                        }
                        continue;
                    }

                    // Check for too many waiting writers
                    if ((knownState & LockStates.WaitingWritersMask) == LockStates.WaitingWritersMask)
                    {
                        Helpers.Sleep(1000);
                        spinCount = 0;
                        currentState = _state;
                        continue;
                    }

                    ++spinCount;

                    // Check if events are being cached. The purpose of this check is that "caching" events could involve
                    // disposing one or both of {_readerEvent, _writerEvent}. This check prevents the waiting code below from
                    // trying to use these events during this dangerous time, and instead causes the loop to spin until the
                    // caching state is cleared and events can be recreated. See ReleaseEvents() and callers.
                    if ((knownState & LockStates.CachingEvents) == LockStates.CachingEvents)
                    {
                        if (spinCount > DefaultSpinCount)
                        {
                            Helpers.Sleep(1);
                            spinCount = 0;
                        }
                        currentState = _state;
                        continue;
                    }

                    // Check spin count
                    if (spinCount <= DefaultSpinCount)
                    {
                        currentState = _state;
                        continue;
                    }

                    // Add to waiting writers
                    currentState = Interlocked.CompareExchange(ref _state, knownState + LockStates.WaitingWriter, knownState);
                    if (currentState != knownState)
                    {
                        continue;
                    }

                    int modifyState = -LockStates.WaitingWriter;
                    AutoResetEvent writerEvent = null;
                    bool waitSucceeded = false;
                    try
                    {
                        writerEvent = GetOrCreateWriterEvent();
                        waitSucceeded = writerEvent.WaitOne(millisecondsTimeout);

                        if (waitSucceeded)
                        {
                            // Become a writer and remove the writer-signaled state
                            Debug.Assert((_state & LockStates.WriterSignaled) != 0);
                            modifyState += LockStates.Writer - LockStates.WriterSignaled;
                        }
                    }
                    finally
                    {
                        // Make the state changes determined above
                        knownState = Interlocked.Add(ref _state, modifyState) - modifyState;

                        if (!waitSucceeded &&
                            (knownState & LockStates.WriterSignaled) != 0 &&
                            (knownState & LockStates.WaitingWritersMask) == LockStates.WaitingWriter)
                        {
                            if (writerEvent == null)
                            {
                                writerEvent = _writerEvent;
                                Debug.Assert(writerEvent != null);
                            }

                            while (true)
                            {
                                knownState = _state;
                                if ((knownState & LockStates.WriterSignaled) == 0 ||
                                    (knownState & LockStates.WaitingWritersMask) != 0)
                                {
                                    break;
                                }

                                if (!writerEvent.WaitOne(10))
                                {
                                    continue;
                                }

                                modifyState = LockStates.Writer - LockStates.WriterSignaled;
                                knownState = Interlocked.Add(ref _state, modifyState) - modifyState;
                                Debug.Assert((knownState & LockStates.WriterSignaled) != 0);
                                Debug.Assert((knownState & LockStates.Writer) == 0);

                                // Honor the orginal status
                                _writerID = threadID;
                                Debug.Assert(_writerLevel == 0);
                                _writerLevel = 1;
                                ReleaseWriterLock();
                                break;
                            }
                        }
                    }

                    if (!waitSucceeded)
                    {
                        throw GetTimeoutException();
                    }
                    break;
                } while (YieldProcessor());
            }

            // Success
            Debug.Assert((_state & LockStates.Writer) != 0);
            Debug.Assert((_state & LockStates.ReadersMask) == 0);
            Debug.Assert(_writerID == InvalidThreadID);

            // Save threadid of the writer
            _writerID = threadID;
            _writerLevel = 1;
            ++_writerSeqNum;
            return;
        }

Same methods

ReaderWriterLock::AcquireWriterLock ( System.TimeSpan timeout ) : void

Usage Example

Esempio n. 1
1
        private static void LockOnReaderWriterLock()
        {
            Console.WriteLine("About to lock on the ReaderWriterLock. Debug after seeing \"Signaled to acquire the reader lock.\"");
            ReaderWriterLock rwLock = new ReaderWriterLock();

            ManualResetEvent rEvent = new ManualResetEvent(false);
            ManualResetEvent pEvent = new ManualResetEvent(false);

            ThreadPool.QueueUserWorkItem((object state) =>
            {
                rwLock.AcquireWriterLock(-1);
                Console.WriteLine("Writer lock acquired!");
                rEvent.Set();
                pEvent.WaitOne();
            });

            rEvent.WaitOne();

            Console.WriteLine("Signaled to acquire the reader lock.");

            rwLock.AcquireReaderLock(-1);

            Console.WriteLine("Reader lock acquired");

            pEvent.Set();

            Console.WriteLine("About to end the program. Press any key to exit.");
            Console.ReadKey();
        }
All Usage Examples Of System.Threading.ReaderWriterLock::AcquireWriterLock