private @Nullable RunnableInfo pollNextEvent() {
    synchronized (getQueueLock()) {
      ModalityState currentModality = LaterInvocator.getCurrentModalityState();

      while (true) {
        final RunnableInfo info = myQueue.pollFirst();
        if (info == null) {
          return null;
        }
        if (info.expired.value(null)) {
          continue;
        }
        if (!currentModality.dominates(info.modalityState)) {
          requestFlush(); // in case someone wrote "invokeLater { UIUtil.dispatchAllInvocationEvents(); }"
          return info;
        }
        //MAYBE RC: probably better to copy 'info' on re-appending the tasks back to the myQueue
        //          (in .reincludeSkippedItems()) and also reset queueSize/queuedTimeNs fields.
        //          This way we got queue loading info 'cleared' (kind of) from bypassing influence,
        //          i.e. re-appended tasks will look as-if they were just added -- which is not strictly true,
        //          but it will disturb waiting times much less than the current approach there skipped/not skipped
        //          tasks waiting times stats are merged together.
        mySkippedItems.add(info.wasSkipped());
      }
    }
  }
private @Nullable RunnableInfo pollNextEvent()