code: void completed(Exception throwable) {
          boolean needToFire = true;
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
              Tr.debug(tc, "completed", throwable.getMessage());
          }
          synchronized (this.completedSemaphore) {
              // future can already be completed
              if (this.completed || !this.channel.isOpen()) {
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, "Future completed after already cancelled or socket was closed");
                  }
                  return;
              }
              this.completed = true;
  
              // new timeout code - cancel active timeout request
              if (getTimeoutWorkItem() != null) {
                  getTimeoutWorkItem().state = TimerWorkItem.ENTRY_CANCELLED;
              }
  
              this.exception = throwable;
  
              if (this.firstListener == null) {
                  // Sync Read/Write request.
                  // must do this inside the sync, or else syncRead/Write could complete
                  // before we get here, and we would be doing this on the next
                  // read/write request!
                  needToFire = false;
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, "doing notify for future " + this);
                  }
                  this.completedSemaphore.notifyAll();
              }
          } // end of sync
  
          if (needToFire) {
              // ASync Read/Write request.
              // need to do this outside the sync, or else we will hold the sync
              // for the user's callback.
              fireCompletionActions();
          }
  
      }
docs: Marks this call as fully completed, but that it completed with an error.
  The error is described by the parameter. Note that the thread that
  invokes this method also runs the code in the callback function, which
  is arbitrarily long (as it is user code).
  
  @param throwable