code: public void flush(final long targetCounter) throws IOException {
      if (targetCounter <= mFlushCounter.get()) {
        return;
      }
      // Using reentrant lock, since it seems to result in higher throughput than using 'synchronized'
      mFlushLock.lock();
      try {
        long startTime = System.nanoTime();
        long flushCounter = mFlushCounter.get();
        if (targetCounter <= flushCounter) {
          // The specified counter is already flushed, so just return.
          return;
        }
        long writeCounter = mWriteCounter.get();
        while (targetCounter > writeCounter) {
          for (;;) {
            // Get, but do not remove, the head entry.
            JournalEntry entry = mQueue.peek();
            if (entry == null) {
              // No more entries in the queue. Break out of the infinite for-loop.
              break;
            }
            mJournalWriter.write(entry);
            // Remove the head entry, after the entry was successfully written.
            mQueue.poll();
            writeCounter = mWriteCounter.incrementAndGet();
  
            if (writeCounter >= targetCounter) {
              if ((System.nanoTime() - startTime) >= mFlushBatchTimeNs) {
                // This thread has been writing to the journal for enough time. Break out of the
                // infinite for-loop.
                break;
              }
            }
          }
        }
        mJournalWriter.flush();
        mFlushCounter.set(writeCounter);
      } finally {
        mFlushLock.unlock();
      }
    }
docs: Flushes and waits until the specified counter is flushed to the journal. If the specified
  counter is already flushed, this is essentially a no-op.
  
  @param targetCounter the counter to flush