@Override
  public void handlerStatusChange(MessageHandler handler, boolean connected) {
    final int numSessions = _sessions.length;

    boolean allDisconnected = true;

    for (int i = 0; i < numSessions; i++) {
      SessionWrapper sessW = _sessions[i];

      if (sessW._session == handler) {
        if (connected != sessW._connected) {
          final NonBlockingSession sess = sessW._session;

          _log.info(
              "MultiSession OutDispatcher "
                  + getComponentId()
                  + " : "
                  + ((connected) ? "CONNECTED" : "DISCONNECTED")
                  + " with "
                  + sess.getComponentId()
                  + ", canHandle="
                  + sess.canHandle()
                  + ", isLoggedIn="
                  + sess.isLoggedIn());

          sessW._connected = connected;
        }
      }

      if (sessW._connected) {
        allDisconnected = false;
      }
    }

    _fullyFlushed = false;

    synchronized (_disconnectLock) { // force mem barrier
      _allDisconnected = allDisconnected;
    }

    _ctl.statusChange();
  }
  @Override
  public void execute() throws Exception {

    _curSessW = _sessions[_nextSession];

    final MessageQueue queue = _curSessW._queue;
    final MessageQueue preQueue = _curSessW._preQueue;
    final NonBlockingSession sess = _curSessW._session;

    if (++_nextSession >= _sessions.length) _nextSession = 0;

    if (_curSessW._connected && sess.canHandle()) {
      if (sess.isLoggedIn()) {
        if (sess.isMsgPendingWrite()) {
          sess.retryCompleteWrite();
        } else if (preQueue.isEmpty()) {
          _curMsg = queue.poll(); // POLL = non blocking, causes MEM_READ barrier
          if (_curMsg != null && _curMsg.getReusableType() != CoreReusableType.NullMessage) {
            sess.handleNow(_curMsg);
          }
        } else { // QUEUED MESSAGES FROM PREVIOUS FLUSH CALLS
          _curMsg = preQueue.next();
          if (_curMsg.getReusableType() != CoreReusableType.NullMessage) {
            sess.handleNow(_curMsg);
          }
        }
      } else { // SYNC mode
        final MessageQueue syncQueue = _curSessW._syncQueue;
        if (sess.isMsgPendingWrite()) {
          sess.retryCompleteWrite();
        } else if (!syncQueue.isEmpty()) {
          _curMsg = syncQueue.next();
          if (_curMsg.getReusableType() != CoreReusableType.NullMessage) {
            sess.handleNow(_curMsg);
          }
        }
      }
    } else {
      flush(_curSessW);
    }
  }