// @NOTE keep flush private the preQ is not threadsafe
  private void flush(SessionWrapper sessW) {
    // disconnected drop any session messages
    // optionally keep any other messages or reject back  upstream

    final Session session = sessW._session;
    final MessageQueue queue = sessW._queue;
    final MessageQueue preQ = sessW._preQueue;
    final MessageQueue syncQ = sessW._syncQueue;

    while (!syncQ.isEmpty()) {
      syncQ.next(); // DISCARD
    }

    Message head = null;
    Message tail = null;

    while (!queue.isEmpty()) {
      Message msg = queue.next();
      if (msg.getReusableType() == CoreReusableType.NullMessage) break;

      if (session.discardOnDisconnect(msg) == false) {
        if (session.rejectMessageUpstream(msg, DISCONNECTED)) {
          // message recycled by successful reject processing
        } else {
          if (tail == null) {
            head = msg;
            tail = msg;
          } else {
            tail.attachQueue(msg);
            tail = msg;
          }
        }
      } else {
        _logMsg.copy(DROP_MSG).append(msg.getReusableType().toString());
        _log.info(_logMsg);
        session.outboundRecycle(msg);
      }
    }

    // move remaining messages to the preQ

    if (head != null) {
      Message tmp = head;

      while (tmp != null) {
        Message next = tmp.getNextQueueEntry();
        tmp.detachQueue();
        preQ.add(tmp);
        tmp = next;
      }
    }
  }
  @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);
    }
  }