/// <summary>Dequeues an item, and then fixes up our state around writers and completion.</summary> /// <returns>The dequeued item.</returns> private T DequeueItemAndPostProcess() { BoundedChannel <T> parent = _parent; Debug.Assert(Monitor.IsEntered(parent.SyncObj)); // Dequeue an item. T item = parent._items.DequeueHead(); // If we're now empty and we're done writing, complete the channel. if (parent._doneWriting != null && parent._items.IsEmpty) { ChannelUtilities.Complete(parent._completion, parent._doneWriting); } // If there are any writers blocked, there's now room for at least one // to be promoted to have its item moved into the items queue. We need // to loop while trying to complete the writer in order to find one that // hasn't yet been canceled (canceled writers transition to canceled but // remain in the physical queue). while (!parent._blockedWriters.IsEmpty) { WriterInteractor <T> w = parent._blockedWriters.DequeueHead(); if (w.Success(default(VoidResult))) { parent._items.EnqueueTail(w.Item); return(item); } } // There was no blocked writer, so see if there's a WaitToWriteAsync // we should wake up. ChannelUtilities.WakeUpWaiters(ref parent._waitingWriters, result: true); // Return the item return(item); }
public override bool TryRead(out T item) { UnbufferedChannel <T> parent = _parent; lock (parent.SyncObj) { parent.AssertInvariants(); // Try to find a writer to pair with while (!parent._blockedWriters.IsEmpty) { WriterInteractor <T> w = parent._blockedWriters.DequeueHead(); if (w.Success(default(VoidResult))) { item = w.Item; return(true); } } } // None found item = default; return(false); }