docs: void completed(long bytesAffected) {
          boolean needToFire = true;
          synchronized (this.completedSemaphore) {
              // If it's already completed, do nothing
              if (this.completed || !this.channel.isOpen()) {
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, "Future completed after already cancelled or socket was closed");
                  }
                  return;
              }
              // mark it completed, release sync lock, then process
              this.completed = true;
  
              // new timeout code - cancel timeout request if active
              if (getTimeoutWorkItem() != null) {
                  getTimeoutWorkItem().state = TimerWorkItem.ENTRY_CANCELLED;
              }
  
              this.byteCount = bytesAffected;
              // Loop over the buffers, updating the positions until
              // we've exhausted the number of bytes affected
              long numbytes = bytesAffected;
              for (ByteBuffer buffer : this.buffers) {
                  int bufspace = buffer.remaining();
                  if (bytesAffected > bufspace) {
                      buffer.position(buffer.limit());
                      numbytes -= bufspace;
                  } else {
                      buffer.position(buffer.position() + (int) numbytes);
                      numbytes = 0;
                      break;
                  }
              } // end for
  
              if (this.firstListener == null) {
                  // Sync Read/Write request.
                  // must do this inside the sync, or else Sync Read/Write could complete
                  // before we get here, and we would be doing this on the next
                  // Read/Write request!
                  needToFire = false;
                  this.completedSemaphore.notifyAll();
              }
          }
  
          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();
          }
      }