// // Constructor: registers a take with a blocking queue. // internal StRegisteredTake(StBlockingQueue <T> queue, StTakeCallback <T> callback, object cbState, int timeout, bool executeOnce) { // // Validate the arguments. // if (timeout == 0) { throw new ArgumentOutOfRangeException("\"timeout\" can not be zero"); } if (callback == null) { throw new ArgumentOutOfRangeException("\"callback\" must be specified"); } // // Initialize the registered take fields. // this.queue = queue; cbparker = new CbParker(UnparkCallback); if ((this.timeout = timeout) != Timeout.Infinite) { toTimer = new RawTimer(cbparker); } this.executeOnce = executeOnce; this.callback = callback; this.cbState = cbState; // // Execute the TryTakePrologue prologue on the queue. // waitNode = queue.TryTakePrologue(cbparker, StParkStatus.Success, out dataItem, ref hint); // // Set the state to active and enable the unpark callback. // state = ACTIVE; int ws; if ((ws = cbparker.EnableCallback(timeout, toTimer)) != StParkStatus.Pending) { // // The take operation was already accomplished. To prevent // uncontrolled reentrancy, the unpark callback is executed inline. // UnparkCallback(ws); } }
// // Exchanges a data item asynchronously. The specified callback gets called // when the exchange completes and is passed the received data item. // // TODO: Prevent unbounded reentrancy (hacked by queueing to the pool). // public ExchangeRegistration RegisterExchange(T myData, ExchangeCallback <T> callback, object state, int timeout) { if (timeout == 0) { throw new ArgumentOutOfRangeException("timeout", "The timeout can't be zero"); } if (callback == null) { throw new ArgumentNullException("callback"); } T yourData; if (TryExchange(myData, out yourData)) { ThreadPool.QueueUserWorkItem(_ => callback(state, yourData, false)); return(new ExchangeRegistration()); } state = state ?? this; WaitNode wn = null; var cbparker = new CbParker(ws => { if (ws != StParkStatus.Success && xchgPoint == wn) { Interlocked.CompareExchange(ref xchgPoint, null, wn); } if (ws != StParkStatus.WaitCancelled) { callback(state, wn.Channel, ws == StParkStatus.Timeout); } }); wn = new WaitNode(cbparker, myData); if (TryExchange(wn, myData, out yourData)) { ThreadPool.QueueUserWorkItem(_ => callback(state, yourData, false)); return(new ExchangeRegistration()); } var timer = timeout != Timeout.Infinite ? new RawTimer(cbparker) : null; int waitStatus = cbparker.EnableCallback(timeout, timer); if (waitStatus != StParkStatus.Pending) { ThreadPool.QueueUserWorkItem(_ => callback(state, wn.Channel, waitStatus == StParkStatus.Timeout)); return(new ExchangeRegistration()); } return(new ExchangeRegistration(cbparker)); }
// // Constructors. // public StTimer(bool notificationTimer) { if (notificationTimer) { tmrEvent = new StNotificationEvent(); } else { tmrEvent = new StSynchronizationEvent(); } state = INACTIVE; cbparker = new CbParker(TimerCallback); timer = new RawTimer(cbparker); }
// // Constructor: registers a wait with a Waitable synchronizer. // internal StRegisteredWait(StWaitable waitObject, WaitOrTimerCallback callback, object cbState, int timeout, bool executeOnce) { // // Validate the arguments. // if (timeout == 0) { throw new ArgumentOutOfRangeException("\"timeout\" can't be zero"); } if (callback == null) { throw new ArgumentOutOfRangeException("\"callback\" can't be null"); } if ((waitObject is StReentrantFairLock) || (waitObject is StReentrantReadWriteLock)) { throw new InvalidOperationException("can't register waits on reentrant locks"); } if ((waitObject is StNotificationEvent) && !executeOnce) { throw new InvalidOperationException("Notification event can't register waits" + " to execute more than once"); } // // Initialize the register wait fields // waitable = waitObject; cbparker = new CbParker(UnparkCallback); toTimer = new RawTimer(cbparker); this.timeout = timeout; this.executeOnce = executeOnce; this.callback = callback; this.cbState = (cbState != null) ? cbState : this; // // Execute the WaitAny prologue on the waitable. // int ignored = 0; waitBlock = waitObject._WaitAnyPrologue(cbparker, StParkStatus.Success, ref hint, ref ignored); // // Set the registered wait state to active and enable the // unpark callback. // state = ACTIVE; int ws = cbparker.EnableCallback(timeout, toTimer); if (ws != StParkStatus.Pending) { // // The acquire operation was already accomplished. To prevent // uncontrolled reentrancy, the unpark callback is executed inline. // UnparkCallback(ws); } }