@Override
  <A> Future<Void> implConnect(
      SocketAddress remote, A attachment, CompletionHandler<Void, ? super A> handler) {
    if (!isOpen()) {
      Throwable exc = new ClosedChannelException();
      if (handler == null) return CompletedFuture.withFailure(exc);
      Invoker.invoke(this, handler, attachment, null, exc);
      return null;
    }

    InetSocketAddress isa = Net.checkAddress(remote);

    // permission check
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());

    // check and update state
    // ConnectEx requires the socket to be bound to a local address
    IOException bindException = null;
    synchronized (stateLock) {
      if (state == ST_CONNECTED) throw new AlreadyConnectedException();
      if (state == ST_PENDING) throw new ConnectionPendingException();
      if (localAddress == null) {
        try {
          bind(new InetSocketAddress(0));
        } catch (IOException x) {
          bindException = x;
        }
      }
      if (bindException == null) state = ST_PENDING;
    }

    // handle bind failure
    if (bindException != null) {
      try {
        close();
      } catch (IOException ignore) {
      }
      if (handler == null) return CompletedFuture.withFailure(bindException);
      Invoker.invoke(this, handler, attachment, null, bindException);
      return null;
    }

    // setup task
    PendingFuture<Void, A> result = new PendingFuture<Void, A>(this, handler, attachment);
    ConnectTask task = new ConnectTask<A>(isa, result);
    result.setContext(task);

    // initiate I/O
    if (Iocp.supportsThreadAgnosticIo()) {
      task.run();
    } else {
      Invoker.invokeOnThreadInThreadPool(this, task);
    }
    return result;
  }
    /** 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);
      }
    }
 /** Invoked by handler thread when failed to establish connection. */
 @Override
 public void failed(int error, IOException x) {
   if (isOpen()) {
     closeChannel();
     result.setFailure(x);
   } else {
     result.setFailure(new AsynchronousCloseException());
   }
   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 if timeout expires before it is cancelled */
    void timeout() {
      // synchronize on result as the I/O could complete/fail
      synchronized (result) {
        if (result.isDone()) return;

        // kill further writing before releasing waiters
        enableWriting(true);
        result.setFailure(new InterruptedByTimeoutException());
      }

      // invoke handler without any locks
      Invoker.invoke(result);
    }
    @Override
    // @SuppressWarnings("unchecked")
    public void run() {
      long overlapped = 0L;
      boolean prepared = false;
      boolean pending = false;
      boolean shutdown = false;

      try {
        begin();

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

        // get an OVERLAPPED structure (from the cache or allocate)
        overlapped = ioCache.add(result);
        int n = write0(handle, numBufs, writeBufferArray, overlapped);
        if (n == IOStatus.UNAVAILABLE) {
          // I/O is pending
          pending = true;
          return;
        }
        if (n == IOStatus.EOF) {
          // special case for shutdown output
          shutdown = true;
          throw new ClosedChannelException();
        }
        // write completed immediately
        throw new InternalError("Write completed immediately");
      } catch (Throwable x) {
        // write failed. Enable writing before releasing waiters.
        enableWriting();
        if (!shutdown && (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);
    }
    @Override
    public void failed(int error, IOException x) {
      // return direct buffer to cache if substituted
      releaseBuffers();

      // release waiters if not already released by timeout
      if (!isOpen()) x = new AsynchronousCloseException();

      synchronized (result) {
        if (result.isDone()) return;
        enableWriting();
        result.setFailure(x);
      }
      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);
    }