code: private int dequeue(ChannelHandlerContext ctx, int minConsume) {
          if (queue != null) {
  
              int consumed = 0;
  
              Object msg;
              while ((consumed < minConsume) || config.isAutoRead()) {
                  msg = queue.poll();
                  if (msg == null) {
                      break;
                  }
  
                  ++consumed;
                  ctx.fireChannelRead(msg);
              }
  
              // We're firing a completion event every time one (or more)
              // messages were consumed and the queue ended up being drained
              // to an empty state.
              if (queue.isEmpty() && consumed > 0) {
                  ctx.fireChannelReadComplete();
              }
  
              return consumed;
          }
  
          return 0;
      }
docs: Dequeues one or many (or none) messages depending on the channel's auto
  reading state and returns the number of messages that were consumed from
  the internal queue.
  
  The {@code minConsume} argument is used to force {@code dequeue()} into
  consuming that number of messages regardless of the channel's auto
  reading configuration.
  
  @see #read(ChannelHandlerContext)
  @see #channelRead(ChannelHandlerContext, Object)