/**
  * Return a {@link Context} to its pool if it is not shared.
  *
  * @param ctx - the {@link Context}
  */
 public void returnContext(Context ctx) {
   if (ctx instanceof NIOContext && ((NIOContext) ctx).decrementRefCount() > 0) {
     return;
   }
   if (logger.isLoggable(Level.FINE)) {
     logger.log(Level.FINE, "returnContext() Context : " + ctx);
   }
   ctx.recycle();
   contexts.offer(ctx);
 }
  /**
   * This method handle the processing of all Selector's interest op
   * (OP_ACCEPT,OP_READ,OP_WRITE,OP_CONNECT) by delegating to its Handler. By default, all
   * java.nio.channels.Selector operations are implemented using SelectorHandler. All SelectionKey
   * operations are implemented by SelectionKeyHandler. Finally, ProtocolChain creation/re-use are
   * implemented by InstanceHandler.
   *
   * @param selectorHandler - the {@link SelectorHandler}
   */
  protected void doSelect(SelectorHandler selectorHandler) {
    final NIOContext serverCtx = pollContext(null, null);
    serverCtx.setSelectorHandler(selectorHandler);
    try {
      // Set the SelectionKeyHandler only if the SelectorHandler doesn't define one.
      if (selectorHandler.getSelectionKeyHandler() == null) {
        if (logger.isLoggable(Level.FINE)) {
          logger.log(
              Level.FINE, "Set DefaultSelectionKeyHandler to SelectorHandler: " + selectorHandler);
        }
        SelectionKeyHandler assgnSelectionKeyHandler = null;
        if (selectorHandler.getPreferredSelectionKeyHandler() != null) {
          Class<? extends SelectionKeyHandler> keyHandlerClass =
              selectorHandler.getPreferredSelectionKeyHandler();
          try {
            assgnSelectionKeyHandler = keyHandlerClass.newInstance();
            assgnSelectionKeyHandler.setSelectorHandler(selectorHandler);
          } catch (Exception e) {
            if (logger.isLoggable(Level.WARNING)) {
              logger.log(
                  Level.WARNING,
                  "Exception initializing preffered SelectionKeyHandler '"
                      + keyHandlerClass
                      + "' for the SelectorHandler '"
                      + selectorHandler
                      + "'");
            }
          }
        }
        if (assgnSelectionKeyHandler == null) {
          assgnSelectionKeyHandler = new DefaultSelectionKeyHandler(selectorHandler);
        }
        selectorHandler.setSelectionKeyHandler(assgnSelectionKeyHandler);
      }
      selectorHandler.preSelect(serverCtx);

      Set<SelectionKey> readyKeys = selectorHandler.select(serverCtx);
      if (readyKeys.size() != 0
          && stateHolder.getState(false) == State.STARTED
          && selectorHandler.getStateHolder().getState(false) == State.STARTED) {
        handleSelectedKeys(readyKeys, selectorHandler, serverCtx);
        readyKeys.clear();
      }
      selectorHandler.postSelect(serverCtx);
    } catch (Throwable e) {
      handleSelectException(e, selectorHandler, null);
    } finally {
      contexts.offer(serverCtx);
    }
  }
  /**
   * Get an instance of a {@link NIOContext}
   *
   * @param key {@link SelectionKey}
   * @param opType the current SelectionKey op.
   * @return {@link Context}
   */
  /* package */ public NIOContext pollContext(SelectionKey key, OpType opType) {
    Context context = contexts.poll();
    if (!(context instanceof NIOContext)) {
      throw new RuntimeException("Invalid Context instance: " + context.getClass().getName());
    }
    NIOContext ctx = (NIOContext) context;
    ctx.setController(this);
    ctx.setSelectionKey(key);
    if (opType != null) {
      ctx.setCurrentOpType(opType);
    } else {
      if (key != null) {
        ctx.configureOpType(key);
      }
    }

    if (logger.isLoggable(Level.FINE)) {
      logger.log(Level.FINE, "pollContext(..) Context : " + ctx);
    }
    return ctx;
  }