public void run() {
      int nHandles = 0;
      lastIdleCheckTime = System.currentTimeMillis();

      // Release the lock
      lock.release();

      while (selectable) {
        try {
          int selected = select(SELECT_TIMEOUT);

          nHandles += registerHandles();

          if (nHandles == 0) {
            try {
              lock.acquire();

              if (registerQueue.isEmpty() && cancelQueue.isEmpty()) {
                acceptor = null;
                break;
              }
            } finally {
              lock.release();
            }
          }

          if (selected > 0) {
            processReadySessions(selectedHandles());
          }

          long currentTime = System.currentTimeMillis();
          flushSessions(currentTime);
          nHandles -= unregisterHandles();

          notifyIdleSessions(currentTime);
        } catch (ClosedSelectorException cse) {
          // If the selector has been closed, we can exit the loop
          ExceptionMonitor.getInstance().exceptionCaught(cse);
          break;
        } catch (Exception e) {
          ExceptionMonitor.getInstance().exceptionCaught(e);

          try {
            Thread.sleep(1000);
          } catch (InterruptedException e1) {
          }
        }
      }

      if (selectable && isDisposing()) {
        selectable = false;
        try {
          destroy();
        } catch (Exception e) {
          ExceptionMonitor.getInstance().exceptionCaught(e);
        } finally {
          disposalFuture.setValue(true);
        }
      }
    }
  /**
   * Process a new session : - initialize it - create its chain - fire the CREATED listeners if any
   *
   * @param session The session to create
   * @return true if the session has been registered
   */
  private boolean addNow(S session) {
    boolean registered = false;

    try {
      init(session);
      registered = true;

      // Build the filter chain of this session.
      IoFilterChainBuilder chainBuilder = session.getService().getFilterChainBuilder();
      chainBuilder.buildFilterChain(session.getFilterChain());

      // DefaultIoFilterChain.CONNECT_FUTURE is cleared inside here
      // in AbstractIoFilterChain.fireSessionOpened().
      // Propagate the SESSION_CREATED event up to the chain
      IoServiceListenerSupport listeners =
          ((AbstractIoService) session.getService()).getListeners();
      listeners.fireSessionCreated(session);
    } catch (Throwable e) {
      ExceptionMonitor.getInstance().exceptionCaught(e);

      try {
        destroy(session);
      } catch (Exception e1) {
        ExceptionMonitor.getInstance().exceptionCaught(e1);
      } finally {
        registered = false;
      }
    }

    return registered;
  }
  private int unregisterHandles() {
    int nHandles = 0;

    for (; ; ) {
      AcceptorOperationFuture request = cancelQueue.poll();
      if (request == null) {
        break;
      }

      // close the channels
      for (SocketAddress socketAddress : request.getLocalAddresses()) {
        DatagramChannel handle = boundHandles.remove(socketAddress);

        if (handle == null) {
          continue;
        }

        try {
          close(handle);
          wakeup(); // wake up again to trigger thread death
        } catch (Exception e) {
          ExceptionMonitor.getInstance().exceptionCaught(e);
        } finally {
          nHandles++;
        }
      }

      request.setDone();
    }

    return nHandles;
  }
  private IoSession newSessionWithoutLock(SocketAddress remoteAddress, SocketAddress localAddress)
      throws Exception {
    DatagramChannel handle = boundHandles.get(localAddress);

    if (handle == null) {
      throw new IllegalArgumentException("Unknown local address: " + localAddress);
    }

    IoSession session;

    synchronized (sessionRecycler) {
      session = sessionRecycler.recycle(remoteAddress);

      if (session != null) {
        return session;
      }

      // If a new session needs to be created.
      NioSession newSession = newSession(this, handle, remoteAddress);
      getSessionRecycler().put(newSession);
      session = newSession;
    }

    initSession(session, null, null);

    try {
      this.getFilterChainBuilder().buildFilterChain(session.getFilterChain());
      getListeners().fireSessionCreated(session);
    } catch (Exception e) {
      ExceptionMonitor.getInstance().exceptionCaught(e);
    }

    return session;
  }
  /** Calls {@link IoServiceListener#sessionDestroyed(IoSession)} for all registered listeners. */
  public void fireSessionDestroyed(IoSession session) {
    // Try to remove the remaining empty session set after removal.
    if (managedSessions.remove(Long.valueOf(session.getId())) == null) {
      return;
    }

    // Fire session events.
    session.getFilterChain().fireSessionClosed();

    // Fire listener events.
    try {
      for (IoServiceListener l : listeners) {
        try {
          l.sessionDestroyed(session);
        } catch (Throwable e) {
          ExceptionMonitor.getInstance().exceptionCaught(e);
        }
      }
    } finally {
      // Fire a virtual service deactivation event for the last session of the connector.
      if (session.getService() instanceof IoConnector) {
        boolean lastSession = false;
        synchronized (managedSessions) {
          lastSession = managedSessions.isEmpty();
        }
        if (lastSession) {
          fireServiceDeactivated();
        }
      }
    }
  }
 @SuppressWarnings("unchecked")
 private void notifyListener(IoFutureListener l) {
   try {
     l.operationComplete(this);
   } catch (Throwable t) {
     ExceptionMonitor.getInstance().exceptionCaught(t);
   }
 }
  /**
   * Calls {@link IoServiceListener#serviceIdle(IoService, IdleStatus)} for all registered
   * listeners.
   */
  public void fireServiceIdle(IdleStatus status) {
    if (!activated.get()) {
      return;
    }

    for (IoServiceListener l : listeners) {
      try {
        l.serviceIdle(service, status);
      } catch (Throwable e) {
        ExceptionMonitor.getInstance().exceptionCaught(e);
      }
    }
  }
  /** Calls {@link IoServiceListener#serviceActivated(IoService)} for all registered listeners. */
  public void fireServiceActivated() {
    if (!activated.compareAndSet(false, true)) {
      return;
    }

    activationTime = System.currentTimeMillis();

    for (IoServiceListener l : listeners) {
      try {
        l.serviceActivated(service);
      } catch (Throwable e) {
        ExceptionMonitor.getInstance().exceptionCaught(e);
      }
    }
  }
  /** Calls {@link IoServiceListener#serviceDeactivated(IoService)} for all registered listeners. */
  public void fireServiceDeactivated() {
    if (!activated.compareAndSet(true, false)) {
      return;
    }

    try {
      for (IoServiceListener l : listeners) {
        try {
          l.serviceDeactivated(service);
        } catch (Throwable e) {
          ExceptionMonitor.getInstance().exceptionCaught(e);
        }
      }
    } finally {
      disconnectSessions();
    }
  }
  private int registerHandles() {
    for (; ; ) {
      AcceptorOperationFuture req = registerQueue.poll();

      if (req == null) {
        break;
      }

      Map<SocketAddress, DatagramChannel> newHandles =
          new HashMap<SocketAddress, DatagramChannel>();
      List<SocketAddress> localAddresses = req.getLocalAddresses();

      try {
        for (SocketAddress socketAddress : localAddresses) {
          DatagramChannel handle = open(socketAddress);
          newHandles.put(localAddress(handle), handle);
        }

        boundHandles.putAll(newHandles);

        getListeners().fireServiceActivated();
        req.setDone();

        return newHandles.size();
      } catch (Exception e) {
        req.setException(e);
      } finally {
        // Roll back if failed to bind all addresses.
        if (req.getException() != null) {
          for (DatagramChannel handle : newHandles.values()) {
            try {
              close(handle);
            } catch (Exception e) {
              ExceptionMonitor.getInstance().exceptionCaught(e);
            }
          }

          wakeup();
        }
      }
    }

    return 0;
  }
  /** Creates a new instance. */
  private NioDatagramAcceptor(IoSessionConfig sessionConfig, Executor executor) {
    super(sessionConfig, executor);

    try {
      init();
      selectable = true;
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw new RuntimeIoException("Failed to initialize.", e);
    } finally {
      if (!selectable) {
        try {
          destroy();
        } catch (Exception e) {
          ExceptionMonitor.getInstance().exceptionCaught(e);
        }
      }
    }
  }
  private void processReadySessions(Set<SelectionKey> handles) {
    Iterator<SelectionKey> iterator = handles.iterator();

    while (iterator.hasNext()) {
      SelectionKey key = iterator.next();
      DatagramChannel handle = (DatagramChannel) key.channel();
      iterator.remove();

      try {
        if ((key != null) && key.isValid() && key.isReadable()) {
          readHandle(handle);
        }

        if ((key != null) && key.isValid() && key.isWritable()) {
          for (IoSession session : getManagedSessions().values()) {
            scheduleFlush((NioSession) session);
          }
        }
      } catch (Exception e) {
        ExceptionMonitor.getInstance().exceptionCaught(e);
      }
    }
  }
  /** Calls {@link IoServiceListener#sessionCreated(IoSession)} for all registered listeners. */
  public void fireSessionCreated(IoSession session) {
    boolean firstSession = false;
    if (session.getService() instanceof IoConnector) {
      synchronized (managedSessions) {
        firstSession = managedSessions.isEmpty();
      }
    }

    // If already registered, ignore.
    if (managedSessions.putIfAbsent(Long.valueOf(session.getId()), session) != null) {
      return;
    }

    // If the first connector session, fire a virtual service activation event.
    if (firstSession) {
      fireServiceActivated();
    }

    // Fire session events.
    session.getFilterChain().fireSessionCreated();
    session.getFilterChain().fireSessionOpened();

    int managedSessionCount = managedSessions.size();
    if (managedSessionCount > largestManagedSessionCount) {
      largestManagedSessionCount = managedSessionCount;
    }
    cumulativeManagedSessionCount++;

    // Fire listener events.
    for (IoServiceListener l : listeners) {
      try {
        l.sessionCreated(session);
      } catch (Throwable e) {
        ExceptionMonitor.getInstance().exceptionCaught(e);
      }
    }
  }
    public void run() {
      assert (processorRef.get() == this);

      int nSessions = 0;
      lastIdleCheckTime = System.currentTimeMillis();

      for (; ; ) {
        try {
          // This select has a timeout so that we can manage
          // idle session when we get out of the select every
          // second. (note : this is a hack to avoid creating
          // a dedicated thread).
          long t0 = System.currentTimeMillis();
          int selected = select(SELECT_TIMEOUT);
          long t1 = System.currentTimeMillis();
          long delta = (t1 - t0);

          if ((selected == 0) && !wakeupCalled.get() && (delta < 100)) {
            // Last chance : the select() may have been
            // interrupted because we have had an closed channel.
            if (isBrokenConnection()) {
              LOG.warn("Broken connection");

              // we can reselect immediately
              // set back the flag to false
              wakeupCalled.getAndSet(false);

              continue;
            } else {
              LOG.warn("Create a new selector. Selected is 0, delta = " + (t1 - t0));
              // Ok, we are hit by the nasty epoll
              // spinning.
              // Basically, there is a race condition
              // which causes a closing file descriptor not to be
              // considered as available as a selected channel, but
              // it stopped the select. The next time we will
              // call select(), it will exit immediately for the same
              // reason, and do so forever, consuming 100%
              // CPU.
              // We have to destroy the selector, and
              // register all the socket on a new one.
              registerNewSelector();
            }

            // Set back the flag to false
            wakeupCalled.getAndSet(false);

            // and continue the loop
            continue;
          }

          // Manage newly created session first
          nSessions += handleNewSessions();

          updateTrafficMask();

          // Now, if we have had some incoming or outgoing events,
          // deal with them
          if (selected > 0) {
            // LOG.debug("Processing ..."); // This log hurts one of the MDCFilter test...
            process();
          }

          // Write the pending requests
          long currentTime = System.currentTimeMillis();
          flush(currentTime);

          // And manage removed sessions
          nSessions -= removeSessions();

          // Last, not least, send Idle events to the idle sessions
          notifyIdleSessions(currentTime);

          // Get a chance to exit the infinite loop if there are no
          // more sessions on this Processor
          if (nSessions == 0) {
            processorRef.set(null);

            if (newSessions.isEmpty() && isSelectorEmpty()) {
              // newSessions.add() precedes startupProcessor
              assert (processorRef.get() != this);
              break;
            }

            assert (processorRef.get() != this);

            if (!processorRef.compareAndSet(null, this)) {
              // startupProcessor won race, so must exit processor
              assert (processorRef.get() != this);
              break;
            }

            assert (processorRef.get() == this);
          }

          // Disconnect all sessions immediately if disposal has been
          // requested so that we exit this loop eventually.
          if (isDisposing()) {
            for (Iterator<S> i = allSessions(); i.hasNext(); ) {
              scheduleRemove(i.next());
            }

            wakeup();
          }
        } catch (ClosedSelectorException cse) {
          // If the selector has been closed, we can exit the loop
          break;
        } catch (Throwable t) {
          ExceptionMonitor.getInstance().exceptionCaught(t);

          try {
            Thread.sleep(1000);
          } catch (InterruptedException e1) {
            ExceptionMonitor.getInstance().exceptionCaught(e1);
          }
        }
      }

      try {
        synchronized (disposalLock) {
          if (disposing) {
            doDispose();
          }
        }
      } catch (Throwable t) {
        ExceptionMonitor.getInstance().exceptionCaught(t);
      } finally {
        disposalFuture.setValue(true);
      }
    }