@Override
  protected void doProcessing() {

    SocketChannel socketChannel;
    while ((socketChannel = accepted.poll()) != null) {
      U.debug("incoming connection", "address", socketChannel.socket().getRemoteSocketAddress());

      try {
        SelectionKey newKey = socketChannel.register(selector, SelectionKey.OP_READ);
        RapidoidConnection conn = connections.get();
        conn.key = newKey;

        if (isProtocolListener) {
          conn.setListener((ConnectionListener) protocol);
        }

        newKey.attach(conn);

      } catch (ClosedChannelException e) {
        U.warn("Closed channel", e);
      }
    }

    synchronized (done) {
      for (int i = 0; i < done.size(); i++) {
        RapidoidConnection conn = done.get(i);
        if (conn.key != null && conn.key.isValid()) {
          conn.key.interestOps(SelectionKey.OP_WRITE);
        }
      }
      done.clear();
    }
  }
  private void close(SelectionKey key) {
    try {
      RapidoidConnection conn = (RapidoidConnection) key.attachment();

      if (key.isValid()) {
        SocketChannel socketChannel = (SocketChannel) key.channel();
        socketChannel.close();
        key.attach(null);
        key.cancel();
      }

      if (conn != null) {
        if (!conn.closed) {
          U.trace("Closing connection", "connection", conn);
          conn.closed = true;
          assert conn.key == key;
          conn.key = null;
          connections.release(conn);
        }
      }

    } catch (IOException e) {
      e.printStackTrace();
    }
  }