Ejemplo n.º 1
0
        internal bool ReceiveFast(RecvChannelOperation recvChannelOperation, Action unlock)
        {
            if (IsBuffered && _msgQueue.Any())
            {
                var msg = _msgQueue.Dequeue();

                if (_msgQueue.Count + 1 == _queueSize && _writerQueue.TryDequeue(out TransferQueueItem writerQueueItemFullMsgQueue))
                {
                    var msgFullMsgQueue = writerQueueItemFullMsgQueue.ChannelOperation.Msg;
                    writerQueueItemFullMsgQueue.ChannelOperation.Notify();
                    _msgQueue.Enqueue(msgFullMsgQueue);
                }
                unlock();

                recvChannelOperation.Msg = msg;
                return(true);
            }

            if (_writerQueue.TryDequeue(out TransferQueueItem writerQueueItem))
            {
                unlock();

                recvChannelOperation.Msg = writerQueueItem.ChannelOperation.Msg;
                writerQueueItem.ChannelOperation.Notify();
                return(true);
            }

            return(false);
        }
Ejemplo n.º 2
0
        internal void AddRecv <T>(Channel <T> channel, Action <T> action)
        {
            if (_channelOperations.Any(co => co.Channel == channel))
            {
                throw new InvalidOperationException("Channel has been already registered in an other case");
            }

            var recvChannelOperation = new RecvChannelOperation(channel, _evt, msg => action((T)msg));

            _channelOperations.Add(recvChannelOperation);
        }
Ejemplo n.º 3
0
        protected async Task <T> RecvCoreAsync <T>()
        {
            if (_isClosed)
            {
                throw new ChannelClosedException();
            }

            Lock();

            if (IsBuffered && _msgQueue.Any())
            {
                var msg = _msgQueue.Dequeue();

                if (_msgQueue.Count + 1 == _queueSize && _writerQueue.TryDequeue(out TransferQueueItem writerQueueItemFullMsgQueue))
                {
                    var msgFullMsgQueue = writerQueueItemFullMsgQueue.ChannelOperation.Msg;
                    writerQueueItemFullMsgQueue.ChannelOperation.Notify();
                    _msgQueue.Enqueue(msgFullMsgQueue);
                }

                Unlock();

                return((T)msg);
            }

            if (_writerQueue.TryDequeue(out TransferQueueItem writerQueueItem))
            {
                Unlock();

                var msg = writerQueueItem.ChannelOperation.Msg;
                writerQueueItem.ChannelOperation.Notify();
                return((T)msg);
            }

            var evt           = new CompletionEvent();
            var recvOperation = new RecvChannelOperation(this, evt);

            _readerQueue.Enqueue(new TransferQueueItem(recvOperation));

            Unlock();

            await evt.WaitAsync();

            if (_isClosed)
            {
                throw new ChannelClosedException();
            }

            return((T)recvOperation.Msg);
        }
Ejemplo n.º 4
0
        internal async Task GoAsync()
        {
            Shuffle();

            LockAllChannels();

            foreach (var channelOperation in _channelOperations)
            {
                if (channelOperation is RecvChannelOperation recvChannelOperation)
                {
                    var channel = channelOperation.Channel;

                    if (channel.ReceiveFast(recvChannelOperation, UnlockAllChannels))
                    {
                        recvChannelOperation.ExecuteAction();
                        return;
                    }
                }
                else
                {
                    var sendChannelOperation = (SendChannelOperation)channelOperation;
                    var channel = channelOperation.Channel;

                    if (channel.IsClosed)
                    {
                        continue;
                    }

                    if (channel.SendFast(sendChannelOperation, UnlockAllChannels))
                    {
                        return;
                    }
                }
            }

            if (_defaultAction != null || _channelOperations.All(c => c.Channel.IsClosed))
            {
                UnlockAllChannels();
                _defaultAction?.Invoke();
                return;
            }

            foreach (var channelOperation in _channelOperations)
            {
                if (channelOperation.Channel.IsClosed)
                {
                    continue;
                }

                if (channelOperation is RecvChannelOperation recvChannelOperation)
                {
                    var channel = channelOperation.Channel;

                    channel.Enqueue(recvChannelOperation, _selectFireContext);
                }
                else
                {
                    var sendChannelOperation = (SendChannelOperation)channelOperation;
                    var channel = channelOperation.Channel;

                    channel.Enqueue(sendChannelOperation, _selectFireContext);
                }
            }

            UnlockAllChannels();

            if (_timer != null)
            {
                var timerChannelOperation = new RecvChannelOperation(_timer.Channel, _evt, _ => _timeoutAction());
                _channelOperations.Add(timerChannelOperation);
                _timer.Channel.Enqueue(timerChannelOperation, _selectFireContext);
                _timer.Start();
            }

            if (_channelOperations.All(c => c.Channel.IsClosed))
            {
                return;
            }

            await _evt.WaitAsync();

            var firedChannelOperation = _selectFireContext.Fired.ChannelOperation;

            if (firedChannelOperation != null)
            {
                if (!firedChannelOperation.Channel.IsClosed)
                {
                    var firedRecvChannelOperation = firedChannelOperation as RecvChannelOperation;
                    firedRecvChannelOperation?.ExecuteAction();
                }
            }

            _timer?.Close();
        }