/** Executed when the I/O has completed */
    @Override
    @SuppressWarnings("unchecked")
    public void completed(int bytesTransferred, boolean canInvokeDirect) {
      if (bytesTransferred == 0) {
        bytesTransferred = -1; // EOF
      } else {
        updateBuffers(bytesTransferred);
      }

      // return direct buffer to cache if substituted
      releaseBuffers();

      // release waiters if not already released by timeout
      synchronized (result) {
        if (result.isDone()) return;
        enableReading();
        if (scatteringRead) {
          result.setResult((V) Long.valueOf(bytesTransferred));
        } else {
          result.setResult((V) Integer.valueOf(bytesTransferred));
        }
      }
      if (canInvokeDirect) {
        Invoker.invokeUnchecked(result);
      } else {
        Invoker.invoke(result);
      }
    }
    /** Invoked by handler thread when connection established. */
    @Override
    public void completed(int bytesTransferred, boolean canInvokeDirect) {
      Throwable exc = null;
      try {
        begin();
        afterConnect();
        result.setResult(null);
      } catch (Throwable x) {
        // channel is closed or unable to finish connect
        exc = x;
      } finally {
        end();
      }

      // can't close channel while in begin/end block
      if (exc != null) {
        closeChannel();
        result.setFailure(toIOException(exc));
      }

      if (canInvokeDirect) {
        Invoker.invokeUnchecked(result);
      } else {
        Invoker.invoke(result);
      }
    }