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); }
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); }
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); }
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(); }