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); }
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); }