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); }
protected async Task <bool> SendCoreAsync(object msg) { if (_isClosed) { throw new ChannelClosedException(); } Lock(); if (_readerQueue.TryDequeue(out TransferQueueItem readerQueueItem)) { Unlock(); readerQueueItem.ChannelOperation.Msg = msg; readerQueueItem.ChannelOperation.Notify(); return(true); } if (IsBuffered && _msgQueue.Count < _queueSize) { _msgQueue.Enqueue(msg); Unlock(); return(true); } var evt = new CompletionEvent(); var sendOperation = new SendChannelOperation(this, evt, msg); _writerQueue.Enqueue(new TransferQueueItem(sendOperation)); Unlock(); await evt.WaitAsync(); if (_isClosed) { throw new ChannelClosedException(); } return(true); }
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(); }