code: @GuardedBy("evictionLock")
    void maintenance(@Nullable Runnable task) {
      lazySetDrainStatus(PROCESSING_TO_IDLE);
  
      try {
        drainReadBuffer();
  
        drainWriteBuffer();
        if (task != null) {
          task.run();
        }
  
        drainKeyReferences();
        drainValueReferences();
  
        expireEntries();
        evictEntries();
  
        climb();
      } finally {
        if ((drainStatus() != PROCESSING_TO_IDLE) || !casDrainStatus(PROCESSING_TO_IDLE, IDLE)) {
          lazySetDrainStatus(REQUIRED);
        }
      }
    }
docs: Performs the pending maintenance work and sets the state flags during processing to avoid
  excess scheduling attempts. The read buffer, write buffer, and reference queues are
  drained, followed by expiration, and size-based eviction.
  
  @param task an additional pending task to run, or {@code null} if not present