Пример #1
0
        protected ThreadQueueStruct SignalAllWithNoWakeup(
            SignalState signalStateIfNoWaiters,
            SignalState signalStateIfWaiters)
        {
            bool              notified      = false;
            Thread            currentThread = Thread.CurrentThread;
            ThreadEntry       waitDoneThreadEntry;
            ThreadEntry       nextThreadEntry;
            ThreadQueueStruct deferredWakeupQueue = new ThreadQueueStruct();
            int unblockerId = UninitWait;
            int numberOfUnblockedWaiters = 0;
            int entryId = UninitWait;

            // Acquire lock. If you hit assert during acquire, and the code is handling
            // interrupt, you may need to use interrupt aware synchronization classes.
            // See the comment for  InterruptAwareAutoResetEvent, InterruptAwareManualResetEvent,
            // and InterruptAwareMutex for details.
            bool shouldEnable = Processor.DisableInterrupts();

            myLock.Acquire(currentThread);
            try {
                ThreadEntryEnum threadEntryEnum = new ThreadEntryEnum(this.waitingQueue.Head);
                nextThreadEntry = threadEntryEnum.GetNext();

                // Waitdone can move entry from one queue to another. Because of that we have
                // to be extremly careful. We move enumerator always one step ahead.
                if (nextThreadEntry != null)
                {
                    do
                    {
                        waitDoneThreadEntry = nextThreadEntry;
                        entryId             = waitDoneThreadEntry.Id;

                        // Move enumerator one step further - we have to do it before we call
                        // WaitDone otherwise we might be enumerating wrong list because entry
                        // can move lists during WaitDone call
                        nextThreadEntry = threadEntryEnum.GetNext();

                        // We are ready to call waitdone
                        unblockerId = WaitDone(waitDoneThreadEntry,
                                               entryId,
                                               ref deferredWakeupQueue);

                        // Remember if we succesfully signalled someone
                        if (unblockerId == entryId)
                        {
                            numberOfUnblockedWaiters++;
                        }
                    } while (nextThreadEntry != null);
                }

                // If we succesfully signalled someone, record state accordingly
                if (numberOfUnblockedWaiters > 0)
                {
                    // Update signal state in case when waiters are present
                    this.signaled = signalStateIfWaiters;
                }
                else
                {
                    // Don't forget to update state when waiters are not present
                    this.signaled = signalStateIfNoWaiters;
                }
            }
            finally {
                // Release lock
                myLock.Release();

                // Reenable interrupts
                Processor.RestoreInterrupts(shouldEnable);
            }

            return(deferredWakeupQueue);
        }
Пример #2
0
        protected ThreadQueueStruct SignalOneWithNoWakeup(SignalState signalStateIfNoWaiters)
        {
            Thread      currentThread = Thread.CurrentThread;
            ThreadEntry nextThreadEntry;
            ThreadEntry waitDoneThreadEntry;
            int         unblockerId = UninitWait;
            int         entryId     = UninitWait;

            // The method below should allocate struct on the stack!!
            ThreadQueueStruct deferredWakeupQueue = new ThreadQueueStruct();

            bool shouldEnable = Processor.DisableInterrupts();

            myLock.Acquire(currentThread);
            try {
                // Acquire lock. If you hit assert during acquire, and the code is handling
                // interrupt, you may need to use interrupt aware synchronization classes.
                // See the comment for  InterruptAwareAutoResetEvent, InterruptAwareManualResetEvent,
                // and InterruptAwareMutex for details.

                ThreadEntryEnum threadEntryEnum = new ThreadEntryEnum(this.waitingQueue.Head);
                nextThreadEntry = threadEntryEnum.GetNext();

                // Waitdone can move entry from one queue to another. Because of that we have
                // to be extremly careful. We move enumerator always one step ahead.
                if (nextThreadEntry != null)
                {
                    do
                    {
                        waitDoneThreadEntry = nextThreadEntry;
                        entryId             = waitDoneThreadEntry.Id;

                        // Move enumerator one step further - we have to do it before we call
                        // WaitDone otherwise we might be enumerating wrong list because entry
                        // can move lists during WaitDone call
                        nextThreadEntry = threadEntryEnum.GetNext();

                        // Perform actual signal
                        unblockerId = WaitDone(waitDoneThreadEntry,
                                               entryId,
                                               ref deferredWakeupQueue);

                        // We will need to loop until we have an entry that we succefully signalled
                    } while (entryId != unblockerId && nextThreadEntry != null);
                }

                // If we succesfully process signal mark state appropriately
                if (unblockerId != UninitWait && (entryId == unblockerId))
                {
                    // Make sure that state is no longer signalled
                    this.signaled = SignalState.Unsignaled;
                }
                else
                {
                    // Set state to specified by caller
                    signaled = signalStateIfNoWaiters;
                }
            }
            finally {
                // Release lock
                myLock.Release();

                // Reenable interrupts
                Processor.RestoreInterrupts(shouldEnable);
            }

            return(deferredWakeupQueue);
        }