internal static ChannelReceiveAwaiter <T> Waiting(IUniqueOportunity oportunity)
 {
     return(new ChannelReceiveAwaiter <T>
     {
         _asyncState = new AsyncState(),
         _uniqueOportunity = oportunity
     });
 }
 internal static ChannelSendAwaiter <T> Waiting(T value, IUniqueOportunity oportunity)
 {
     return(new ChannelSendAwaiter <T>
     {
         _asyncState = new AsyncState(value),
         _uniqueOportunity = oportunity
     });
 }
Exemple #3
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);
        }
 internal void AsyncPass(IUniqueOportunity oportunity, Action callback)
 {
     _asyncPass(oportunity, callback);
 }
Exemple #5
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;
        }
Exemple #6
0
        internal ChannelSendAwaiter <T> SendAsync(T value, IUniqueOportunity oportunity)
        {
            Action afterLock = null;

            _rwl.EnterWriteLock();
            try
            {
                if (_closing)
                {
                    throw new InvalidOperationException("channel is closed");
                }
                while (_activeReceivers.Count > 0)
                {
                    var receiver = _activeReceivers.First.Value;
                    _activeReceivers.RemoveFirst();
                    if (receiver.LockForSelection())
                    {
                        if (oportunity.TryAcquire())
                        {
                            afterLock = () => receiver.Receive(value);
                            oportunity.Release(false);
                            receiver.ConfirmSelection();
                            return(ChannelSendAwaiter <T> .Done());
                        }
                        else
                        {
                            receiver.CancelSelection();
                            _activeReceivers.AddFirst(receiver);
                            return(ChannelSendAwaiter <T> .Never());
                        }
                    }
                }
                if (_buffer != null && _bufferedCount < _buffer.Length)
                {
                    if (oportunity.TryAcquire())
                    {
                        oportunity.Release(false);
                        _buffer[(_bufferHead + _bufferedCount++) % _buffer.Length] = value;
                        return(ChannelSendAwaiter <T> .Done());
                    }
                    else
                    {
                        return(ChannelSendAwaiter <T> .Never());
                    }
                }
                // cleanup
                var current = _activeSenders.First;
                while (current != null)
                {
                    var old = current;
                    current = old.Next;
                    if (!old.Value.IsStillListening())
                    {
                        _activeSenders.Remove(old);
                    }
                }
                var waiter = ChannelSendAwaiter <T> .Waiting(value, oportunity);

                _activeSenders.AddLast(waiter);
                return(waiter);
            }
            finally
            {
                _rwl.ExitWriteLock();
                afterLock?.Invoke();
            }
        }