示例#1
0
        /// <summary>
        /// Wait on a given position. This will block, until this object has
        /// <see cref="Increment"/> called up to the position indicated. This
        /// accepts cancellation tokens, but the default cancellation token also
        /// works.
        /// </summary>
        public void Wait(long position, CancellationToken token = default(CancellationToken))
        {
            if (_ex != null)
            {
                throw Contracts.Except(_ex, "Event we were waiting on was subject to an exception");
            }
            if (position <= _currCleared)
            {
                return;
            }
            WaitStats ev;

            lock (_waiters)
            {
                // No need to do anything in this strange case.
                if (_ex != null)
                {
                    throw Contracts.Except(_ex, "Event we were waiting on was subject to an exception");
                }
                if (position <= _currCleared)
                {
                    return;
                }
                ev = new WaitStats(position);
                _waiters.Add(ev);
            }
            ev.Event.Wait(token);
            if (_ex != null)
            {
                throw Contracts.Except(_ex, "Event we were waiting on was subject to an exception");
            }
        }
        /// <summary>
        /// Indicates to the waiter that we want to, at some future point, wait at a given
        /// position. This object will return a reset event that can be waited on, at the
        /// point when we actually want to wait. This method itself has the potential to
        /// signal other events, if by registering ourselves the waiter becomes aware of
        /// the maximum number of waiters, allowing that waiter to enter its critical state.
        ///
        /// If multiple events are associated with the minimum value, then only one will
        /// be signaled, and the rest will remain unsignaled. Which is chosen is undefined.
        /// </summary>
        public ManualResetEventSlim Register(long position)
        {
            WaitStats ev;

            lock (_waiters)
            {
                Contracts.Check(_maxWaiters > 0, "All waiters have been retired, Wait should not be called at this point");
                // We should never reach the state
                Contracts.Assert(_waiters.Count < _maxWaiters);
                ev = new WaitStats(position);
                // REVIEW: Optimize the case where this is the minimum?
                _waiters.Add(ev);
                SignalIfNeeded();
                Contracts.Assert(_waiters.Count < _maxWaiters);
            }
            // REVIEW: At first I instead returned an action, ev.Event.Wait.
            // It may be less efficient, but I don't know if returning an action here
            // is really that bad?
            return(ev.Event);
        }