//
        // Tries to wakeup a waiting upgrader and/or all the waiting readers.
        //

        private bool TryWakeupUpgraderAndReaders() {

            //
            // Initialize the wakeup list and the released flag.
            //

            WaitNodeQueue wl = new WaitNodeQueue();
            bool released = false;

            //
            // If the upgraders wait queue isn't empty, try to wakeup a
            // waiting upgrader to enter the lock in upgradeable read mode.
            //

            if (!upQueue.IsEmpty) {
                do {
                    WaitNode w = upQueue.Dequeue();
                    if (w.TryLock()) {

                        //
                        // Make the locked waiter as the current upgrader and
                        // add its wait node to the wake up list.
                        //

                        upgrader = w.tid;
                        wl.AddToWakeList(w);
                        released = true;
                        break;
                    }
                } while (!upQueue.IsEmpty);
            }

            //
            // Even when the r/w lock state changes to the upgrade read mode,
            // all the waiting readers can enter the read lock.
            //

            while (!rdQueue.IsEmpty) {
                WaitNode w = rdQueue.Dequeue();
                if (w.TryLock()) {

                    //
                    // Account for one more active reader, add the respective
                    // entry to the reader owners table and add the waiting reader
                    // to the wake up list.
                    //

                    readers++;
                    rdCounts.Add(w.tid);
                    wl.AddToWakeList(w);
                    released = true;
                }
            }

            //
            // If no thread was released, return false holding the
            // spinlock; otherwise, release the spinlock, unpark all
            // threads inserted in the wake up list and return true.
            //

            if (!released) {
                return false;
            }
            slock.Exit();
            wl.UnparkAll();
            return true;
        }
Exemple #2
0
        //
        // Tries to wakeup a waiting upgrader and/or all the waiting readers.
        //

        private bool TryWakeupUpgraderAndReaders()
        {
            //
            // Initialize the wakeup list and the released flag.
            //

            WaitNodeQueue wl       = new WaitNodeQueue();
            bool          released = false;

            //
            // If the upgraders wait queue isn't empty, try to wakeup a
            // waiting upgrader to enter the lock in upgradeable read mode.
            //

            if (!upQueue.IsEmpty)
            {
                do
                {
                    WaitNode w = upQueue.Dequeue();
                    if (w.TryLock())
                    {
                        //
                        // Make the locked waiter as the current upgrader and
                        // add its wait node to the wake up list.
                        //

                        upgrader = w.tid;
                        wl.AddToWakeList(w);
                        released = true;
                        break;
                    }
                } while (!upQueue.IsEmpty);
            }

            //
            // Even when the r/w lock state changes to the upgrade read mode,
            // all the waiting readers can enter the read lock.
            //

            while (!rdQueue.IsEmpty)
            {
                WaitNode w = rdQueue.Dequeue();
                if (w.TryLock())
                {
                    //
                    // Account for one more active reader, add the respective
                    // entry to the reader owners table and add the waiting reader
                    // to the wake up list.
                    //

                    readers++;
                    rdCounts.Add(w.tid);
                    wl.AddToWakeList(w);
                    released = true;
                }
            }

            //
            // If no thread was released, return false holding the
            // spinlock; otherwise, release the spinlock, unpark all
            // threads inserted in the wake up list and return true.
            //

            if (!released)
            {
                return(false);
            }
            slock.Exit();
            wl.UnparkAll();
            return(true);
        }