internal StWaitBlock (StParker pk, WaitType t, int r, int k) { parker = pk; waitType = t; request = r; waitKey = k; }
private void Run() { VConsole.WriteLine("+++ r #{0} started...", id); Random r = new Random((id + 1) * Environment.TickCount); do { try { int idx = r.Next() % SEMAPHORES; if (idx < sems.Length) { sems[idx].Release(1); } else { handles[idx - sems.Length].Release(1); } releases[id]++; } catch (StSemaphoreFullException) { StParker.Sleep(new StCancelArgs(10)); } Thread.Sleep(0); } while (!shutdown.IsSet); VConsole.WriteLine("+++ releaser #{0} exiting, [{1}]", id, releases[id]); done.Signal(); }
internal StWaitBlock (WaitType t, int r, int k) { parker = new StParker (); waitType = t; request = r; waitKey = k; }
// // Constructors. // public StTimer(bool notificationTimer) { if (notificationTimer) { tmrEvent = new StNotificationEvent(); } else { tmrEvent = new StSynchronizationEvent(); } state = INACTIVE; cbparker = new CbParker(TimerCallback); timer = new RawTimer(cbparker); }
// // Registers the specified parker with the alerter. // internal bool RegisterParker(StParker pk) { do { StParker s; // // If the alerter is already set, return false. // if ((s = state) == ALERTED) { return false; } // // Try to insert the parker in the alert list. // pk.pnext = s; if (Interlocked.CompareExchange<StParker>(ref state, pk, s) == s) { return true; } } while (true); }
internal override StWaitBlock _WaitAnyPrologue (StParker pk, int key, ref StWaitBlock hint, ref int sc) { StWaitBlock wb = null; do { if (_TryAcquire ()) { return null; } if (wb == null) { wb = new StWaitBlock (pk, WaitType.WaitAny, 1, key); } if (EnqueueWaiter (wb, out hint)) { sc = hint == head ? spinCount : 0; return wb; } if (head.next == INFLATED) { return null; } } while (true); }
internal override WaitBlock _WaitAllPrologue(StParker pk, ref WaitBlock ignored, ref int sc) { if (_AllowsAcquire) { return null; } var wb = new WaitBlock(pk, WaitType.WaitAll, 1, StParkStatus.StateChange); sc = EnqueueAcquire(wb, 1); return wb; }
internal override WaitBlock _WaitAnyPrologue(StParker pk, int key, ref WaitBlock ignored, ref int sc) { if (TryAcquireInternal(1)) { return null; } var wb = new WaitBlock(pk, WaitType.WaitAny, 1, key); sc = EnqueueAcquire(wb, 1); return wb; }
// // The construtor. // internal RawTimer(StParker pk) { parker = pk; }
static TimerList() { // // Create the objects. // _lock = new SpinLock(TIMER_LIST_LOCK_SPINS); timerListHead = new RawTimer(null); limitTimer = new RawTimer(null); parker = new StParker(1); // // Initialize the limit timer as unlinked. // limitTimer.next = limitTimer; // // Initialize the timer list as empty. // timerListHead.next = timerListHead.prev = timerListHead; // // Set the start base time e set the *delay* sentinel. // baseTime = Environment.TickCount; timerListHead.delay = Int32.MaxValue; // // Create and start the timer thread. // new Thread(TimerThread).Start(); }
public static int Sleep(StCancelArgs cargs) { int ws = new StParker().Park(0, cargs); StCancelArgs.ThrowIfException(ws); return ws; }
internal override WaitBlock _WaitAnyPrologue(StParker pk, int key, ref WaitBlock hint, ref int sc) { return _TryAcquire() ? null : flock._WaitAnyPrologue(pk, key, ref hint, ref sc); }
// // 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); }
internal WaitBlock(WaitType t, int r) { parker = new StParker(); waitType = t; request = r; }
// // Executes the prologue of the Waitable.WaitAll method. // internal override WaitBlock _WaitAllPrologue(StParker pk, ref WaitBlock hint, ref int sc) { return tmrEvent._WaitAllPrologue(pk, ref hint, ref sc); }
// // Cancels the timer. // public bool Cancel() { // // If the timer is being cancelled from the user callback function, // set the period to zero and return success. The timer will be // cancelled on return from the callback function. // if (cbtid == Thread.CurrentThread.ManagedThreadId) { period = 0; return true; } // // If the timer is active we must try to cancel the timer // and return only after the timer is actually cancelled. // if the timer is already inactive or a cancel or a set is taking // place, this function returns FALSE. // StSpinWait spinner = new StSpinWait(); StParker pk = new StParker(0); StParker oldState; do { if ((oldState = state) == INACTIVE) { return false; } if (oldState == ACTIVE) { if (Interlocked.CompareExchange<StParker>(ref state, pk, ACTIVE) == ACTIVE) { break; } } if (!(oldState is SentinelParker)) { return false; } spinner.SpinOnce(); } while (true); // // Try to cancel the timer's callback parker. If we can't // park the current thread until the timer callback finishes // execution. // if (cbparker.TryCancel()) { cbparker.Unpark(StParkStatus.TimerCancelled); } else { pk.Park(100, StCancelArgs.None); } // // Set the timer state to inactive and return success. // state = INACTIVE; return true; }
// // Sets the timer. // public bool Set(int dueTime, int period, WaitOrTimerCallback callback, object cbState) { // // If the timer is being set from the user callback function, // we just save the new settings and return success. // if (cbtid == Thread.CurrentThread.ManagedThreadId) { this.dueTime = dueTime; this.period = period; useDueTime = true; this.callback = callback; this.cbState = cbState; return true; } // // The timer is being set externally. So, we must first cancel the // timer. If the timer is already being set or cancelled, we return // failure. // StSpinWait spinner = new StSpinWait(); StParker pk = new StParker(0); StParker oldState; do { if ((oldState = state) == INACTIVE) { if (Interlocked.CompareExchange<StParker>(ref state, SETTING, INACTIVE) == INACTIVE) { goto SetTimer; } } else if (oldState == ACTIVE) { if (Interlocked.CompareExchange<StParker>(ref state, pk, ACTIVE) == ACTIVE) { break; } } else if (!(oldState is SentinelParker)) { return false; } spinner.SpinOnce(); } while (true); // // Try to cancel the timer's callback parker. If succeed, // call the unpark method; otherwise, the timer callback is // taking place, so we must synchronize with its end. // if (cbparker.TryCancel()) { cbparker.Unpark(StParkStatus.TimerCancelled); } else { pk.Park(100, StCancelArgs.None); } // // Here, we know that the timer is cancelled and no one else // is trying to set or cancel the timer. // So, set the timer state to *our busy state* and start it with // the new settings. // state = SETTING; SetTimer: this.dueTime = dueTime; this.period = period; useDueTime = false; this.callback = callback; this.cbState = cbState; StNotificationEvent nev = tmrEvent as StNotificationEvent; if (nev != null) { nev.Reset(); } else { ((StSynchronizationEvent)tmrEvent).Reset(); } // // Initialize the timer's parker, set the timer state to ACTIVE // and enable the unpark callback. // cbparker.Reset(); state = ACTIVE; int ws = cbparker.EnableCallback(dueTime, timer); if (ws != StParkStatus.Pending) { // // If the timer already fired or cancelled, call the unpark // callback inline. // TimerCallback(ws); } return true; }
internal override StWaitBlock _WaitAllPrologue (StParker pk, ref StWaitBlock hint, ref int sc) { if (_AllowsAcquire) { return null; } var wb = new StWaitBlock (pk, WaitType.WaitAll, 1, StParkStatus.StateChange); if (EnqueueWaiter (wb, out hint)) { sc = hint == head ? spinCount : 0; return wb; } return null; }
public void Reset(int releasers) { pnext = null; state = releasers | WAIT_IN_PROGRESS; }
// // 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); } }
internal WaitBlock(int r) { parker = new StParker(); request = r; }
// // Unregisters the registered wait. // public bool Unregister() { // // If the unregister is being called from the callback method, // we just set the *onlyOnce* to TRUE and return. // if (cbtid == Thread.CurrentThread.ManagedThreadId) { executeOnce = true; return true; } // // If the wait is registered, we try to unregister it, and return // only after the wait is actually unregistered. // If the wait was already unregistered or an unregister is taking // place, this method returns false. // StSpinWait spinner = new StSpinWait(); StParker pk = new StParker(0); StParker oldState; do { if ((oldState = state) == INACTIVE) { return false; } if (oldState == ACTIVE) { if (Interlocked.CompareExchange<StParker>(ref state, pk, ACTIVE) == ACTIVE) { break; } } else if (!(oldState is SentinelParker)) { return false; } spinner.SpinOnce(); } while (true); // // Try to cancel the wait's callback parker. If we succeed, call // the unpark with status disposed. Otherwise, a callback is taking // place and we must synchronize with its end. // if (cbparker.TryCancel()) { cbparker.Unpark(StParkStatus.WaitCancelled); } else { pk.Park(BUSY_SPINS, StCancelArgs.None); } // // Set the registered wait object to inactive and return success. // state = INACTIVE; return true; }
public void Wait(StParker pk, StCancelArgs cargs) { bool interrupted = false; int lastTime = (cargs.Timeout != Timeout.Infinite) ? Environment.TickCount : 0; int ws; do { try { ws = waitBehavior.Park(psevent, cargs.Timeout); break; } catch (ThreadInterruptedException) { if (cargs.Interruptible) { ws = StParkStatus.Interrupted; break; } interrupted = true; cargs.AdjustTimeout(ref lastTime); } } while (true); // // If the wait was cancelled due to an internal canceller, try // to cancel the park operation. If we fail, wait unconditionally // until the park spot is signalled. // if (ws != StParkStatus.Success) { if (pk.TryCancel()) { pk.UnparkSelf(waitBehavior.ParkerCancelled(ws)); } else { if (ws == StParkStatus.Interrupted) { interrupted = true; } waitBehavior.ParkerNotCancelled(ws); do { try { psevent.WaitOne(); break; } catch (ThreadInterruptedException) { interrupted = true; } } while (true); } } // // If we were interrupted but can't return the *interrupted* // wait status, reassert the interrupt on the current thread. // if (interrupted) { Thread.CurrentThread.Interrupt(); } factory.Free(this); }
// // Executes the prologue of the Waitable.WaitAny method. // internal override WaitBlock _WaitAnyPrologue(StParker pk, int key, ref WaitBlock hint, ref int sc) { return FastTryEnterWrite(Thread.CurrentThread.ManagedThreadId) ? null : rwlock._WaitAnyPrologue(pk, key, ref hint, ref sc); }
// // Slow path to acquire the spin lock. // private void SlowEnter() { StParker pk = null; do { // // First, try to acquire the spin lock, spinning for the // specified number of cycles, if the wait queue is empty. // int sc = spinCount; do { if (state == FREE && Interlocked.CompareExchange(ref state, BUSY, FREE) == FREE) { return; } if (top != null || sc-- <= 0) { break; } Platform.SpinWait(1); } while (true); // // The spin lock is busy. So, create, or reset, a parker and // insert it in the wait queue. // if (pk == null) { pk = new StParker(0); } else { pk.Reset(0); } do { StParker t; pk.pnext = (t = top); if (Interlocked.CompareExchange<StParker>(ref top, pk, t) == t) { break; } } while (true); // // Since that the lock can become free after the parker is // inserted in the wait queue, we must retry to acquire the spinlock // if it seems free. // // NOTE: We don't remove the parker from the wait queue, because // it will be surely removed next time the lock is release. // if (state == FREE && Interlocked.CompareExchange(ref state, BUSY, FREE) == FREE) { return; } // // Park the current thread and, after release, retry the // spin lock acquire. // pk.Park(); } while (true); }
internal override WaitBlock _WaitAllPrologue(StParker pk, ref WaitBlock hint, ref int sc) { return _AllowsAcquire ? null : flock._WaitAllPrologue(pk, ref hint, ref sc); }
// // CASes on the *pnext* field. // internal bool CasNext(StParker n, StParker nn) { return (pnext == n && Interlocked.CompareExchange(ref pnext, nn, n) == n); }
internal WaitBlock(WaitType t) { parker = new StParker(); waitType = t; }
// // 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); }
internal WaitBlock(StParker pk, int r) { parker = pk; request = r; }
// // Constructors. // public SpinLock(int sc) { state = FREE; top = null; spinCount = Platform.IsMultiProcessor ? sc : 0; }