/// <summary> /// Waits until predicate estimates to true or cancellation received or dispose happened /// </summary> private bool WaitUntilPredicate <TState>(WaitPredicate <TState> predicate, TState state, uint startTime, int timeout, CancellationToken token) { TurboContract.Assert(predicate != null, conditionString: "predicate != null"); int remainingWaitMilliseconds = Timeout.Infinite; while (true) { if (token.IsCancellationRequested || _isDisposed) { return(false); } if (timeout != Timeout.Infinite) { remainingWaitMilliseconds = TimeoutHelper.UpdateTimeout(startTime, timeout); if (remainingWaitMilliseconds <= 0) { return(false); } } if (!Monitor.Wait(this, remainingWaitMilliseconds)) { return(false); } if (predicate.Invoke(state)) { return(true); } } }
public bool Wait <TState>(WaitPredicate <TState> predicate, TState state, TimeSpan timeout) { long timeoutMs = (long)timeout.TotalMilliseconds; if (timeoutMs > int.MaxValue) { throw new ArgumentOutOfRangeException(nameof(timeout)); } return(Wait(predicate, state, (int)timeoutMs, default(CancellationToken))); }
/// <summary> /// Blocks the current thread until predicate estimates as True /// </summary> /// <typeparam name="TState">Type of the state object</typeparam> /// <param name="predicate">Predicate that should return True to complete waiting</param> /// <param name="state">State object for the predicate</param> /// <returns>True if predicate evaluates to True</returns> /// <exception cref="ArgumentNullException">predicate is null</exception> /// <exception cref="ObjectDisposedException">ConditionVariable was disposed</exception> /// <exception cref="OperationCanceledException">Cancellation happened</exception> /// <exception cref="OperationInterruptedException">Waiting was interrupted by Dispose</exception> public bool Wait<TState>(WaitPredicate<TState> predicate, TState state) { if (predicate == null) throw new ArgumentNullException(nameof(predicate)); if (_sourceWaiter == null) throw new ObjectDisposedException(nameof(MonitorWaiter), "Lock section has exited"); if (_sourceWaiter.IsDisposed) throw new ObjectDisposedException(nameof(MonitorObject), $"MonitorObject '{_sourceWaiter.Name}' was disposed"); if (_token.IsCancellationRequested) throw new OperationCanceledException(_token); Debug.Assert(_sourceWaiter.IsEntered()); if (predicate(state)) return true; else if (_timeout == 0) return false; int remainingWaitMilliseconds = Timeout.Infinite; while (!_token.IsCancellationRequested && !_sourceWaiter.IsDisposed) { if (_timeout != Timeout.Infinite) { remainingWaitMilliseconds = TimeoutHelper.UpdateTimeout(_startTime, _timeout); if (remainingWaitMilliseconds <= 0) break; } if (!Monitor.Wait(_sourceWaiter, remainingWaitMilliseconds)) break; if (predicate.Invoke(state)) return true; } // Check if cancellation or dispose was the reasons of the signal if (_token.IsCancellationRequested) throw new OperationCanceledException(_token); if (_sourceWaiter.IsDisposed) throw new OperationInterruptedException("Wait was interrupted by Dispose", new ObjectDisposedException(nameof(MonitorObject), $"MonitorObject '{_sourceWaiter.Name}' was disposed")); // Final check for predicate return predicate(state); }
/// <summary> /// Blocks the current thread until predicate estimates as True /// </summary> /// <typeparam name="TState">Type of the state object</typeparam> /// <param name="predicate">Predicate that should return True to complete waiting</param> /// <param name="state">State object for the predicate</param> /// <param name="timeout">Tiemout in milliseconds</param> /// <param name="token">Cancellation token</param> /// <returns>True if predicate evaluates to True</returns> /// <exception cref="ArgumentNullException">predicate is null</exception> /// <exception cref="SynchronizationLockException">externalLock is not acquired or acquired recursively</exception> /// <exception cref="ObjectDisposedException">ConditionVariable was disposed</exception> /// <exception cref="OperationCanceledException">Cancellation happened</exception> /// <exception cref="OperationInterruptedException">Waiting was interrupted by Dispose</exception> public bool Wait <TState>(WaitPredicate <TState> predicate, TState state, int timeout, CancellationToken token) { if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } if (!Monitor.IsEntered(_externalLock)) { throw new SynchronizationLockException("External lock should be acquired"); } if (_isDisposed) { throw new ObjectDisposedException(this.GetType().Name); } if (token.IsCancellationRequested) { throw new OperationCanceledException(token); } uint startTime = 0; if (timeout > 0) { startTime = TimeoutHelper.GetTimestamp(); } if (predicate(state)) { return(true); } if (timeout == 0) { return(false); } return(WaitSlowPath(predicate, state, startTime, timeout, token)); }
/// <summary> /// Blocks the current thread until predicate estimates as True /// </summary> /// <typeparam name="TState">Type of the state object</typeparam> /// <param name="predicate">Predicate that should return True to complete waiting</param> /// <param name="state">State object for the predicate</param> /// <returns>True if predicate evaluates to True</returns> /// <exception cref="ArgumentNullException">predicate is null</exception> /// <exception cref="ObjectDisposedException">ConditionVariable was disposed</exception> /// <exception cref="OperationCanceledException">Cancellation happened</exception> /// <exception cref="OperationInterruptedException">Waiting was interrupted by Dispose</exception> public bool Wait <TState>(WaitPredicate <TState> predicate, TState state) { if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } if (_sourceWaiter == null) { throw new ObjectDisposedException(nameof(ConditionVariableWaiter), "Lock section has exited"); } if (_sourceWaiter.IsDisposed) { throw new ObjectDisposedException(nameof(ConditionVariable), $"ConditionVariable '{_sourceWaiter.Name}' was disposed"); } if (_token.IsCancellationRequested) { throw new OperationCanceledException(_token); } TurboContract.Assert(_sourceWaiter.IsEntered(), conditionString: "_sourceWaiter.IsEntered()"); if (predicate(state)) { return(true); } else if (_timeout == 0) { return(false); } if (_timeout > 0 && TimeoutHelper.UpdateTimeout(_startTime, _timeout) <= 0) // Predicate estimation took too much time { return(false); } bool internalLockTaken = false; bool externalLockTaken = true; try { try { } finally { Monitor.Enter(_sourceWaiter.InternalLock, ref internalLockTaken); TurboContract.Assert(internalLockTaken, conditionString: "internalLockTaken"); } if (WaitUntilPredicate(ref internalLockTaken, ref externalLockTaken, predicate, state)) { return(true); } // Check if cancellation or dispose was the reasons of the signal if (_token.IsCancellationRequested) { throw new OperationCanceledException(_token); } if (_sourceWaiter.IsDisposed) { throw new OperationInterruptedException("Wait was interrupted by Dispose", new ObjectDisposedException(nameof(ConditionVariable), $"ConditionVariable '{_sourceWaiter.Name}' was disposed")); } } finally { if (internalLockTaken) { Monitor.Exit(_sourceWaiter.InternalLock); } EnterLock(_sourceWaiter.ExternalLock, ref externalLockTaken); } // Final check for predicate return(predicate(state)); }
private bool WaitUntilPredicate <TState>(ref bool internalLockTaken, ref bool externalLockTaken, WaitPredicate <TState> predicate, TState state) { TurboContract.Requires(internalLockTaken, "internalLockTaken == false"); TurboContract.Requires(externalLockTaken, "externalLockTaken == false"); TurboContract.Requires(predicate != null, conditionString: "predicate != null"); int remainingWaitMilliseconds = Timeout.Infinite; while (true) { if (_token.IsCancellationRequested || _sourceWaiter.IsDisposed) { return(false); } if (_timeout != Timeout.Infinite) { remainingWaitMilliseconds = TimeoutHelper.UpdateTimeout(_startTime, _timeout); if (remainingWaitMilliseconds <= 0) { return(false); } } ExitLock(_sourceWaiter.ExternalLock, ref externalLockTaken); if (!Monitor.Wait(_sourceWaiter.InternalLock, remainingWaitMilliseconds)) { return(false); } try { ExitLock(_sourceWaiter.InternalLock, ref internalLockTaken); EnterLock(_sourceWaiter.ExternalLock, ref externalLockTaken); if (predicate.Invoke(state)) { return(true); } } finally { EnterLock(_sourceWaiter.InternalLock, ref internalLockTaken); } } }
public bool Wait <TState>(WaitPredicate <TState> predicate, TState state, CancellationToken token) { return(Wait(predicate, state, Timeout.Infinite, token)); }
public bool Wait <TState>(WaitPredicate <TState> predicate, TState state, int timeout) { return(Wait(predicate, state, timeout, default(CancellationToken))); }
/// <summary> /// Slow path /// </summary> private bool WaitSlowPath <TState>(WaitPredicate <TState> predicate, TState state, uint startTime, int timeout, CancellationToken token) { if (token.IsCancellationRequested) { throw new OperationCanceledException(token); } if (timeout < 0) { timeout = Timeout.Infinite; } if (timeout > 0 && TimeoutHelper.UpdateTimeout(startTime, timeout) <= 0) // Predicate estimation took too much time { return(false); } CancellationTokenRegistration cancellationTokenRegistration = default(CancellationTokenRegistration); bool internalLockTaken = false; bool externalLockTaken = true; try { if (token.CanBeCanceled) { cancellationTokenRegistration = CancellationTokenHelper.RegisterWithoutECIfPossible(token, _cancellationTokenCanceledEventHandler, this); } try { } finally { Monitor.Enter(_internalLock, ref internalLockTaken); TurboContract.Assert(internalLockTaken, conditionString: "internalLockTaken"); _waitCount++; } if (WaitUntilPredicate(ref internalLockTaken, ref externalLockTaken, predicate, state, startTime, timeout, token)) { return(true); } if (token.IsCancellationRequested) { throw new OperationCanceledException(token); } if (_isDisposed) { throw new OperationInterruptedException("Wait was interrupted by Dispose", new ObjectDisposedException(this.GetType().Name)); } } finally { if (internalLockTaken) { _waitCount--; TurboContract.Assert(_waitCount >= 0, conditionString: "_waitCount >= 0"); Monitor.Exit(_internalLock); } EnterLock(_externalLock, ref externalLockTaken); cancellationTokenRegistration.Dispose(); } // Final check for predicate return(predicate(state)); }
private bool WaitUntilPredicate <TState>(ref bool internalLockTaken, ref bool externalLockTaken, WaitPredicate <TState> predicate, TState state, uint startTime, int timeout, CancellationToken token) { TurboContract.Requires(internalLockTaken, "internalLockTaken == false"); TurboContract.Requires(externalLockTaken, "externalLockTaken == false"); TurboContract.Requires(predicate != null, conditionString: "predicate != null"); int remainingWaitMilliseconds = Timeout.Infinite; bool recursiveLockChecked = false; while (true) { if (token.IsCancellationRequested || _isDisposed) { return(false); } if (timeout != Timeout.Infinite) { remainingWaitMilliseconds = TimeoutHelper.UpdateTimeout(startTime, timeout); if (remainingWaitMilliseconds <= 0) { return(false); } } ExitLock(_externalLock, ref externalLockTaken); if (!recursiveLockChecked && Monitor.IsEntered(_externalLock)) // Sanity check { throw new SynchronizationLockException("Recursive lock is not supported"); } recursiveLockChecked = true; if (!Monitor.Wait(_internalLock, remainingWaitMilliseconds)) { return(false); } try { ExitLock(_internalLock, ref internalLockTaken); EnterLock(_externalLock, ref externalLockTaken); if (predicate.Invoke(state)) { return(true); } } finally { EnterLock(_internalLock, ref internalLockTaken); } } }
/// <summary> /// Blocks the current thread until predicate estimates as True /// </summary> /// <typeparam name="TState">Type of the state object</typeparam> /// <param name="predicate">Predicate that should return True to complete waiting</param> /// <param name="state">State object for the predicate</param> /// <param name="timeout">Tiemout in milliseconds</param> /// <param name="token">Cancellation token</param> /// <returns>True if predicate evaluates to True</returns> /// <exception cref="ArgumentNullException">predicate is null</exception> /// <exception cref="SynchronizationLockException">Lock is not acquired</exception> /// <exception cref="ObjectDisposedException">Waiter was disposed</exception> /// <exception cref="OperationCanceledException">Cancellation happened</exception> /// <exception cref="OperationInterruptedException">Waiting was interrupted by Dispose</exception> public bool Wait <TState>(WaitPredicate <TState> predicate, TState state, int timeout, CancellationToken token) { if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } if (!Monitor.IsEntered(this)) { throw new SynchronizationLockException("External lock should be acquired"); } if (_isDisposed) { throw new ObjectDisposedException(this.GetType().Name); } if (token.IsCancellationRequested) { throw new OperationCanceledException(token); } uint startTime = 0; if (timeout > 0) { startTime = TimeoutHelper.GetTimestamp(); } else if (timeout < -1) { timeout = Timeout.Infinite; } if (predicate(state)) { return(true); } if (timeout == 0) { return(false); } if (timeout > 0 && TimeoutHelper.UpdateTimeout(startTime, timeout) <= 0) // Predicate estimation took too much time { return(false); } CancellationTokenRegistration cancellationTokenRegistration = default(CancellationTokenRegistration); try { if (token.CanBeCanceled) { cancellationTokenRegistration = CancellationTokenHelper.RegisterWithoutECIfPossible(token, _cancellationTokenCanceledEventHandler, this); } if (WaitUntilPredicate(predicate, state, startTime, timeout, token)) { return(true); } if (token.IsCancellationRequested) { throw new OperationCanceledException(token); } if (_isDisposed) { throw new OperationInterruptedException("Wait was interrupted by Dispose", new ObjectDisposedException(this.GetType().Name)); } } finally { cancellationTokenRegistration.Dispose(); } // Final check for predicate return(predicate(state)); }
/// <summary> /// Blocks the current thread until predicate estimates as True /// </summary> /// <typeparam name="TState">Type of the state object</typeparam> /// <param name="predicate">Predicate that should return True to complete waiting</param> /// <param name="state">State object for the predicate</param> /// <returns>True if predicate evaluates to True</returns> /// <exception cref="ArgumentNullException">predicate is null</exception> /// <exception cref="ObjectDisposedException">ConditionVariable was disposed</exception> /// <exception cref="OperationCanceledException">Cancellation happened</exception> /// <exception cref="OperationInterruptedException">Waiting was interrupted by Dispose</exception> public bool Wait <TState>(WaitPredicate <TState> predicate, TState state) { if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } if (_sourceWaiter == null) { throw new ObjectDisposedException(nameof(ConditionVariableWaiter), "Lock section has exited"); } if (_sourceWaiter.IsDisposed) { throw new ObjectDisposedException(nameof(ConditionVariable), $"ConditionVariable '{_sourceWaiter.Name}' was disposed"); } if (_token.IsCancellationRequested) { throw new OperationCanceledException(_token); } Debug.Assert(_sourceWaiter.IsEntered()); if (predicate(state)) { return(true); } else if (_timeout == 0) { return(false); } if (_timeout > 0 && TimeoutHelper.UpdateTimeout(_startTime, _timeout) <= 0) // Predicate estimation took too much time { return(false); } int remainingWaitMilliseconds = Timeout.Infinite; var waitingPrimitive = _sourceWaiter.RegisterWaiter(); bool firstTry = true; while (!_token.IsCancellationRequested && !_sourceWaiter.IsDisposed) { try { if (waitingPrimitive.IsSet || firstTry) { firstTry = false; waitingPrimitive.Reset(); _sourceWaiter.AddWaiterToQueue(waitingPrimitive); } Monitor.Exit(_sourceWaiter.ExternalLock); if (Monitor.IsEntered(_sourceWaiter.ExternalLock)) { throw new SynchronizationLockException("Recursive lock is not supported"); } if (_timeout != Timeout.Infinite) { remainingWaitMilliseconds = TimeoutHelper.UpdateTimeout(_startTime, _timeout); if (remainingWaitMilliseconds <= 0) { break; } } if (!waitingPrimitive.Wait(remainingWaitMilliseconds)) { break; } } finally { Monitor.Enter(_sourceWaiter.ExternalLock); if (!waitingPrimitive.IsSet) { _sourceWaiter.RemoveWaiterFromQueue(waitingPrimitive); } } if (predicate(state)) { return(true); } } // Check if cancellation or dispose was the reasons of the signal if (_token.IsCancellationRequested) { throw new OperationCanceledException(_token); } if (_sourceWaiter.IsDisposed) { throw new OperationInterruptedException("Wait was interrupted by Dispose", new ObjectDisposedException(nameof(ConditionVariableAlt), $"ConditionVariable '{_sourceWaiter.Name}' was disposed")); } // Final check for predicate return(predicate(state)); }