Ejemplo n.º 1
0
        private bool WaitUntilPredicate <TState>(ref bool internalLockTaken, ref bool externalLockTaken, WaitPredicateRef <TState> predicate, ref 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(ref state))
                    {
                        return(true);
                    }
                }
                finally
                {
                    EnterLock(_sourceWaiter.InternalLock, ref internalLockTaken);
                }
            }
        }
Ejemplo n.º 2
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>(WaitPredicateRef<TState> predicate, ref 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(ref 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(ref 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(ref state);
        }