コード例 #1
0
        /// <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);
                }
            }
        }
コード例 #2
0
        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)));
        }
コード例 #3
0
        /// <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);
        }
コード例 #4
0
        /// <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));
        }
コード例 #5
0
        /// <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));
        }
コード例 #6
0
        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);
                }
            }
        }
コード例 #7
0
 public bool Wait <TState>(WaitPredicate <TState> predicate, TState state, CancellationToken token)
 {
     return(Wait(predicate, state, Timeout.Infinite, token));
 }
コード例 #8
0
 public bool Wait <TState>(WaitPredicate <TState> predicate, TState state, int timeout)
 {
     return(Wait(predicate, state, timeout, default(CancellationToken)));
 }
コード例 #9
0
        /// <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));
        }
コード例 #10
0
        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);
                }
            }
        }
コード例 #11
0
        /// <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));
        }
コード例 #12
0
        /// <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));
        }