// // Executes the unpark callback. // private void UnparkCallback(int ws) { Debug.Assert(ws == StParkStatus.Success || ws == StParkStatus.Timeout || ws == StParkStatus.WaitCancelled); // // If the registered wait was cancelled, cancel the acquire // attempt and return immediately. // if (ws == StParkStatus.WaitCancelled) { waitable._CancelAcquire(waitBlock, hint); return; } // // Set state to *our busy* grabing the current state, and execute // the unpark callback processing. // StParker myBusy = new SentinelParker(); StParker oldState = Interlocked.Exchange <StParker>(ref state, myBusy); do { // // If the acquire operation was cancelled, cancel the acquire // attempt on the waitable. // if (ws != StParkStatus.Success) { waitable._CancelAcquire(waitBlock, hint); } // // Execute the user callback routine. // cbtid = Thread.CurrentThread.ManagedThreadId; callback(cbState, ws == StParkStatus.Timeout); cbtid = 0; // // If the registered wait was configured to execute once or // there is an unregister in progress, set the state to INACTIVE. // If a thread is waiting to unregister, unpark it. // if (executeOnce || !(oldState is SentinelParker)) { if (!(oldState is SentinelParker)) { oldState.Unpark(StParkStatus.Success); } else { state = INACTIVE; } return; } // // We must re-register with the Waitable. // So, initialize the parker and execute the WaitAny prologue. // cbparker.Reset(1); int ignored = 0; waitBlock = waitable._WaitAnyPrologue(cbparker, StParkStatus.Success, ref hint, ref ignored); // // Enable the unpark callback. // ws = cbparker.EnableCallback(timeout, toTimer); if (ws == StParkStatus.Pending) { // // If the *state* field constains still *my busy* set it to ACTIVE. // if (state == myBusy) { Interlocked.CompareExchange <StParker>(ref state, ACTIVE, myBusy); } return; } // // The waitable was already signalled. So, execute the unpark // callback inline. // } while (true); }
// // Executes the unpark callback. // private void UnparkCallback(int ws) { Debug.Assert(ws == StParkStatus.Success || ws == StParkStatus.Timeout || ws == StParkStatus.TakeCancelled); // // If the registered take was cancelled, cancel the take attempt // and return immediately. // if (ws == StParkStatus.TakeCancelled) { queue.CancelTakeAttempt(waitNode, hint); return; } // // Set state to *our busy*, grabing the current state. // StParker myBusy = new SentinelParker(); StParker oldState = Interlocked.Exchange <StParker>(ref state, myBusy); do { // // If the take operation succeeded, execute the take epilogue; // otherwise, cancel the take attempt. // if (ws == StParkStatus.Success) { queue.TakeEpilogue(); } else { queue.CancelTakeAttempt(waitNode, hint); } // // Execute the user callback routine. // cbtid = Thread.CurrentThread.ManagedThreadId; callback(cbState, waitNode == null ? dataItem : waitNode.channel, ws == StParkStatus.Timeout); cbtid = 0; // // If the registered take was configured to execute once or // there is an unregister in progress, set the state to INACTIVE. // If a thread is waiting to unregister, unpark it. // if (executeOnce || !(oldState is SentinelParker)) { if (!(oldState is SentinelParker)) { oldState.Unpark(StParkStatus.Success); } else { state = INACTIVE; } return; } // // We must re-register with the queue. // So, initialize the parker and execute the TakeAny prologue. // cbparker.Reset(); waitNode = queue.TryTakePrologue(cbparker, StParkStatus.Success, out dataItem, ref hint); // // Enable the unpark callback. // if ((ws = cbparker.EnableCallback(timeout, toTimer)) == StParkStatus.Pending) { // // If the *state* field is still *my busy* set it to ACTIVE; // anyway, return. // if (state == myBusy) { Interlocked.CompareExchange <StParker>(ref state, ACTIVE, myBusy); } return; } // // The take was already accomplished; so, to prevent uncontrolled // reentrancy execute the unpark callback inline. // } while (true); }
// // Executes the timer callback // internal void TimerCallback(int ws) { Debug.Assert(ws == StParkStatus.Timeout || ws == StParkStatus.TimerCancelled); // // If the timer was cancelled, return immediately. // if (ws == StParkStatus.TimerCancelled) { return; } // // Set timer state to *our busy* state, grabing the current state and // execute the timer callback processing. // SentinelParker myBusy = new SentinelParker(); StParker oldState = Interlocked.Exchange <StParker>(ref state, myBusy); do { // // Signals the timer's event. // tmrEvent.Signal(); // // Call the user-defined callback, if specified. // if (callback != null) { cbtid = Thread.CurrentThread.ManagedThreadId; callback(cbState, true); cbtid = 0; } // // If the timer isn't periodic or if someone is trying to // cancel it, process cancellation. // if (period == 0 || !(oldState is SentinelParker)) { if (!(oldState is SentinelParker)) { oldState.Unpark(StParkStatus.Success); } else { state = INACTIVE; } return; } // // Initialize the timer's parker. // cbparker.Reset(); // // Compute the timer delay and enable the unpark callback. // int timeout; if (useDueTime) { timeout = dueTime; useDueTime = false; } else { timeout = period | (1 << 31); } if ((ws = cbparker.EnableCallback(timeout, timer)) == StParkStatus.Pending) { if (state == myBusy) { Interlocked.CompareExchange <StParker>(ref state, ACTIVE, myBusy); } return; } // // The timer already expired. So, execute the timer // callback inline. // } while (true); }