Esempio n. 1
0
        internal ChannelReceiveAwaiter <T> ReceiveAsync(IUniqueOportunity oportunity)
        {
            ChannelReceiveAwaiter <T>         result         = default(ChannelReceiveAwaiter <T>);
            Func <ChannelReceiveAwaiter <T> > indirectResult = null;

            _rwl.EnterWriteLock();
            try
            {
                ReceiveAsyncInternal(ref result, ref indirectResult, oportunity);
            }
            finally
            {
                _rwl.ExitWriteLock();
            }
            if (indirectResult != null)
            {
                return(indirectResult());
            }
            return(result);
        }
Esempio n. 2
0
        private void ReceiveAsyncInternal(ref ChannelReceiveAwaiter <T> result, ref Func <ChannelReceiveAwaiter <T> > indirectResult, IUniqueOportunity oportunity)
        {
            if (_buffer != null && _bufferedCount > 0)
            {
                if (oportunity.TryAcquire())
                {
                    oportunity.Release(false);
                    result = ChannelReceiveAwaiter <T> .Done(_buffer[_bufferHead]);

                    _buffer[_bufferHead] = default(T);
                    _bufferHead          = (_bufferHead + 1) % _buffer.Length;
                    --_bufferedCount;
                    if (_closing && _bufferedCount == 0 && _activeSenders.Count == 0)
                    {
                        _closed = true;
                    }
                    return;
                }
                else
                {
                    result = ChannelReceiveAwaiter <T> .Never();
                }
            }
            while (_activeSenders.Count > 0)
            {
                var sender = _activeSenders.First.Value;
                _activeSenders.RemoveFirst();
                if (sender.LockForSelection())
                {
                    if (oportunity.TryAcquire())
                    {
                        sender.ConfirmSelection();
                        oportunity.Release(false);
                        indirectResult = () => ChannelReceiveAwaiter <T> .Done(sender.Consume());

                        if (_closing && _bufferedCount == 0 && _activeSenders.Count == 0)
                        {
                            _closed = true;
                        }
                        return;
                    }
                    else
                    {
                        sender.CancelSelection();
                        _activeSenders.AddFirst(sender);
                        result = ChannelReceiveAwaiter <T> .Never();

                        return;
                    }
                }
            }
            if (_closed)
            {
                if (oportunity.TryAcquire())
                {
                    oportunity.Release(false);
                    result = ChannelReceiveAwaiter <T> .Done(default(T));

                    return;
                }
                else
                {
                    result = ChannelReceiveAwaiter <T> .Never();

                    return;
                }
            }
            // cleanup
            var current = _activeReceivers.First;

            while (current != null)
            {
                var old = current;
                current = old.Next;
                if (!old.Value.IsStillListening())
                {
                    _activeReceivers.Remove(old);
                }
            }
            var waiter = ChannelReceiveAwaiter <T> .Waiting(oportunity);

            _activeReceivers.AddLast(waiter);
            result = waiter;
        }