private void CheckWaitingReads() { if (!readLocked.HasValue && waitingReads.Count > 0) { WaitingRead wr = waitingReads.Peek(); if (items.Count >= wr.desiredItems || (eofSignaled && !writeLocked.HasValue && waitingWrites.Count == 0)) { waitingReads.Dequeue(); readLocked = Math.Min(wr.desiredItems, items.Count); wr.k.PostResult(new AcquireReadSucceeded <T>(readPtr, readLocked.Value == 0 ? ImmutableList <T> .Empty : items.GetRange(0, readLocked.Value))); if (wr.ctr.HasValue) { wr.ctr.Value.PostDispose(); } if (readLocked.Value == 0) { while (waitingReads.Count > 0) { WaitingRead wr2 = waitingReads.Dequeue(); wr2.k.PostResult(new AcquireReadSucceeded <T>(readPtr, ImmutableList <T> .Empty)); if (wr2.ctr.HasValue) { wr2.ctr.Value.PostDispose(); } } } } } }
/// <inheritdoc /> public Task <AcquireReadResult> AcquireReadAsync(int desiredItems, CancellationToken ctoken) { if (desiredItems < 1) { return(Task.FromResult <AcquireReadResult>(new AcquireReadFaulted(new ArgumentOutOfRangeException("desiredItems", "Must be at least one")))); } if (ctoken.IsCancellationRequested) { return(Task.FromResult <AcquireReadResult>(new AcquireReadCancelled())); } else { lock (syncRoot) { if (!readLocked.HasValue && (items.Count >= desiredItems || eofSignaled)) { readLocked = Math.Min(items.Count, desiredItems); return(Task.FromResult <AcquireReadResult>(new AcquireReadSucceeded <T>(readPtr, items.GetRange(0, readLocked.Value)))); } else { TaskCompletionSource <AcquireReadResult> k = new TaskCompletionSource <AcquireReadResult>(); WaitingRead wr = new WaitingRead() { id = null, desiredItems = desiredItems, k = k, ctr = null, }; long id = waitingReads.Enqueue(wr); wr.id = id; ctoken.PostRegistration(ctr => SetRegistrationForAcquireRead(id, ctr), () => CancelAcquireRead(id)); return(k.Task); } } } }