public OutputStreamQueueReader <TPayload> CreateReader()
        {
            lock (this)
            {
                var seq   = _lastSequenceNumber + 1;
                var last  = _readyQueue.Last;
                int count = 0;
                while (last != null)
                {
                    var lastPacket = last.Value.Data;
                    if ((lastPacket.Payload.Properties.Flags & 1) > 0 && lastPacket.SourceId == 0)
                    {
                        seq = lastPacket.SequenceNumber;
                        break;
                    }

                    last = last.Previous;
                    count++;
                }

                Core.LogInfo($"Adding reader, to be sent {count} additionally");
                var result = new OutputStreamQueueReader <TPayload>
                {
                    CurrentSequenceNumber = seq
                };
                _readers.Add(result);
                return(result);
            }
        }
 public void RemoveReader(OutputStreamQueueReader <TPayload> reader)
 {
     lock (this)
     {
         _readers.Remove(reader);
         Clean();
     }
 }
        public OutputStreamQueueDataReference <TPayload> Dequeue(OutputStreamQueueReader <TPayload> reader, ref bool continueProcessing, out int dropped)
        {
            lock (this)
            {
                while (continueProcessing && reader.CurrentSequenceNumber > _lastSequenceNumber)
                {
                    Monitor.Wait(this);
                }

                reader.BufferSize = _lastSequenceNumber - reader.CurrentSequenceNumber;
                if (continueProcessing)
                {
                    if (reader.CurrentSequenceNumber < _readyQueue.First.Value.Data.SequenceNumber)
                    {
                        dropped = _readyQueue.First.Value.Data.SequenceNumber - reader.CurrentSequenceNumber;
                        reader.CurrentSequenceNumber = _readyQueue.First.Value.Data.SequenceNumber + 1;

                        return(_readyQueue.First.Value.AddReference());
                    }
                    else
                    {
                        var last = _readyQueue.Last;

                        while (last.Value.Data.SequenceNumber != reader.CurrentSequenceNumber)
                        {
                            last = last.Previous;
                        }

                        dropped = 0;
                        reader.CurrentSequenceNumber++;

                        var result = last.Value.AddReference();

                        if (last.Previous == null) // it is first
                        {
                            Clean();
                        }

                        return(result);
                    }
                }
                else
                {
                    dropped = 0;
                    return(null);
                }
            }
        }