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