private void addWriteTimeoutTask(WriteTimeoutTask task) {
   if (lastTask == null) {
     lastTask = task;
   } else {
     lastTask.next = task;
     task.prev = lastTask;
     lastTask = task;
   }
 }
  private void scheduleTimeout(final ChannelHandlerContext ctx, final ChannelPromise promise) {
    // Schedule a timeout.
    final WriteTimeoutTask task = new WriteTimeoutTask(ctx, promise);
    task.scheduledFuture = ctx.executor().schedule(task, timeoutNanos, TimeUnit.NANOSECONDS);

    if (!task.scheduledFuture.isDone()) {
      addWriteTimeoutTask(task);

      // Cancel the scheduled timeout if the flush promise is complete.
      promise.addListener(task);
    }
  }
 @Override
 public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
   WriteTimeoutTask task = lastTask;
   lastTask = null;
   while (task != null) {
     task.scheduledFuture.cancel(false);
     WriteTimeoutTask prev = task.prev;
     task.prev = null;
     task.next = null;
     task = prev;
   }
 }
 private void removeWriteTimeoutTask(WriteTimeoutTask task) {
   if (task == lastTask) {
     // task is the tail of list
     assert task.next == null;
     lastTask = lastTask.prev;
     if (lastTask != null) {
       lastTask.next = null;
     }
   } else if (task.prev == null && task.next == null) {
     // Since task is not lastTask, then it has been removed or not been added.
     return;
   } else if (task.prev == null) {
     // task is the head of list and the list has at least 2 nodes
     task.next.prev = null;
   } else {
     task.prev.next = task.next;
     task.next.prev = task.prev;
   }
   task.prev = null;
   task.next = null;
 }