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