/** {@inheritDoc} */
 @Override
 public AsyncSocketChannelImpl shutdown(ShutdownType how) throws IOException {
   final Socket socket = channel.socket();
   try {
     if (how == ShutdownType.READ || how == ShutdownType.BOTH) {
       if (!socket.isInputShutdown()) {
         socket.shutdownInput();
         key.selected(OP_READ);
       }
     }
     if (how == ShutdownType.WRITE || how == ShutdownType.BOTH) {
       if (!socket.isOutputShutdown()) {
         socket.shutdownOutput();
         key.selected(OP_WRITE);
       }
     }
   } catch (SocketException e) {
     if (!socket.isConnected()) {
       throw Util.initCause(new NotYetConnectedException(), e);
     }
     if (socket.isClosed()) {
       throw Util.initCause(new ClosedChannelException(), e);
     }
     throw e;
   }
   return this;
 }
  /** {@inheritDoc} */
  @Override
  public <A> IoFuture<Void, A> connect(
      SocketAddress remote, final A attachment, final CompletionHandler<Void, ? super A> handler) {
    try {
      if (channel.connect(remote)) {
        Future<Void> result = Util.finishedFuture(null);
        key.runCompletion(handler, attachment, result);
        return AttachedFuture.wrap(result, attachment);
      }
    } catch (ClosedChannelException e) {
      throw Util.initCause(new ClosedAsynchronousChannelException(), e);
    } catch (IOException e) {
      Future<Void> result = Util.failedFuture(e);
      key.runCompletion(handler, attachment, result);
      return AttachedFuture.wrap(result, attachment);
    }

    return key.execute(
        OP_CONNECT,
        attachment,
        handler,
        0,
        TimeUnit.MILLISECONDS,
        new Callable<Void>() {
          public Void call() throws IOException {
            try {
              channel.finishConnect();
              return null;
            } catch (ClosedChannelException e) {
              throw Util.initCause(new AsynchronousCloseException(), e);
            }
          }
        });
  }
  /** {@inheritDoc} */
  @Override
  public <A> IoFuture<Long, A> write(
      final ByteBuffer[] srcs,
      final int offset,
      final int length,
      long timeout,
      TimeUnit unit,
      A attachment,
      CompletionHandler<Long, ? super A> handler) {
    if ((offset < 0) || (offset >= srcs.length)) {
      throw new IllegalArgumentException("offset out of range");
    }
    if ((length < 0) || (length > (srcs.length - offset))) {
      throw new IllegalArgumentException("length out of range");
    }

    return key.execute(
        OP_WRITE,
        attachment,
        handler,
        timeout,
        unit,
        new Callable<Long>() {
          public Long call() throws IOException {
            try {
              return channel.write(srcs, offset, length);
            } catch (ClosedChannelException e) {
              throw Util.initCause(new AsynchronousCloseException(), e);
            }
          }
        });
  }
 /** {@inheritDoc} */
 @Override
 public <A> IoFuture<Integer, A> read(
     final ByteBuffer dst,
     long timeout,
     TimeUnit unit,
     A attachment,
     CompletionHandler<Integer, ? super A> handler) {
   if (timeout == 0) {
     timeout = socketTimeout;
     unit = TimeUnit.MILLISECONDS;
   }
   return key.execute(
       OP_READ,
       attachment,
       handler,
       timeout,
       unit,
       new Callable<Integer>() {
         public Integer call() throws IOException {
           try {
             return channel.read(dst);
           } catch (ClosedChannelException e) {
             throw Util.initCause(new AsynchronousCloseException(), e);
           }
         }
       });
 }
 /** {@inheritDoc} */
 @Override
 public <A> IoFuture<Integer, A> write(
     final ByteBuffer src,
     long timeout,
     TimeUnit unit,
     A attachment,
     CompletionHandler<Integer, ? super A> handler) {
   return key.execute(
       OP_WRITE,
       attachment,
       handler,
       timeout,
       unit,
       new Callable<Integer>() {
         public Integer call() throws IOException {
           try {
             return channel.write(src);
           } catch (ClosedChannelException e) {
             throw Util.initCause(new AsynchronousCloseException(), e);
           }
         }
       });
 }
 /** {@inheritDoc} */
 @Override
 public <A> IoFuture<AsynchronousSocketChannel, A> accept(
     A attachment, CompletionHandler<AsynchronousSocketChannel, ? super A> handler) {
   return key.execute(
       OP_ACCEPT,
       attachment,
       handler,
       0,
       TimeUnit.MILLISECONDS,
       new Callable<AsynchronousSocketChannel>() {
         public AsynchronousSocketChannel call() throws IOException {
           try {
             SocketChannel newChannel = channel.accept();
             if (newChannel == null) {
               // TODO re-execute on the key somehow? -JM
               throw new IOException("accept failed");
             }
             return new AsyncSocketChannelImpl(group, newChannel);
           } catch (ClosedChannelException e) {
             throw Util.initCause(new AsynchronousCloseException(), e);
           }
         }
       });
 }
 /** {@inheritDoc} */
 @Override
 public boolean isWritePending() {
   return key.isOpPending(OP_WRITE);
 }
 /** {@inheritDoc} */
 @Override
 public boolean isReadPending() {
   return key.isOpPending(OP_READ);
 }
 /** {@inheritDoc} */
 @Override
 public void close() throws IOException {
   key.close();
 }
 /** {@inheritDoc} */
 @Override
 public boolean isAcceptPending() {
   return key.isOpPending(OP_ACCEPT);
 }