/** 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);
      }
    }
    @Override
    @SuppressWarnings("unchecked")
    public void run() {
      long overlapped = 0L;
      boolean prepared = false;
      boolean pending = false;

      try {
        begin();

        // substitute non-direct buffers
        prepareBuffers();
        prepared = true;

        // get an OVERLAPPED structure (from the cache or allocate)
        overlapped = ioCache.add(result);

        // initiate read
        int n = read0(handle, numBufs, readBufferArray, overlapped);
        if (n == IOStatus.UNAVAILABLE) {
          // I/O is pending
          pending = true;
          return;
        }
        if (n == IOStatus.EOF) {
          // input shutdown
          enableReading();
          if (scatteringRead) {
            result.setResult((V) Long.valueOf(-1L));
          } else {
            result.setResult((V) Integer.valueOf(-1));
          }
        } else {
          throw new InternalError("Read completed immediately");
        }
      } catch (Throwable x) {
        // failed to initiate read
        // reset read flag before releasing waiters
        enableReading();
        if (x instanceof ClosedChannelException) x = new AsynchronousCloseException();
        if (!(x instanceof IOException)) x = new IOException(x);
        result.setFailure(x);
      } finally {
        // release resources if I/O not pending
        if (!pending) {
          if (overlapped != 0L) ioCache.remove(overlapped);
          if (prepared) releaseBuffers();
        }
        end();
      }

      // invoke completion handler
      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);
      }
    }
    /** Task to initiate a connection. */
    @Override
    public void run() {
      long overlapped = 0L;
      Throwable exc = null;
      try {
        begin();

        // synchronize on result to allow this thread handle the case
        // where the connection is established immediately.
        synchronized (result) {
          overlapped = ioCache.add(result);
          // initiate the connection
          int n =
              connect0(
                  handle, Net.isIPv6Available(), remote.getAddress(), remote.getPort(), overlapped);
          if (n == IOStatus.UNAVAILABLE) {
            // connection is pending
            return;
          }

          // connection established immediately
          afterConnect();
          result.setResult(null);
        }
      } catch (Throwable x) {
        if (overlapped != 0L) ioCache.remove(overlapped);
        exc = x;
      } finally {
        end();
      }

      if (exc != null) {
        closeChannel();
        result.setFailure(toIOException(exc));
      }
      Invoker.invoke(result);
    }