epareForUse(final @NotNull PageContentLoader contentLoader) throws IOException {
    final int packedState = this.statePacked;
    final int state = unpackState(packedState);
    if (state == STATE_NOT_READY_YET) {
      final int usageCount = unpackUsageCount(packedState);
      if (usageCount != 0) {
        throw new AssertionError("Bug: usageCount(=" + usageCount + ") must be 0 in NOT_READ_YET: " + this);
      }

      final int newPackedState = packState(STATE_LOADING, 0);

      if (STATE_UPDATER.compareAndSet(this, packedState, newPackedState)) {
        this.auxDebugData = Thread.currentThread();
        try {
          this.data = contentLoader.loadPageContent(this);
          //Current thread exclusively owns the page in LOADING state, so no need for CAS here:
          this.statePacked = packState(STATE_USABLE, 0);
          return true;
        }
        catch (Throwable e) {
          //MAYBE RC: it is better to immediately transition page to TOMBSTONE? This simplifies logic:
          //          no 'backward' transitions, page either loaded, or failed and entombed, and it is
          //          up PagedStorage implementation to decide do another attempt to load page or not.
          //          Downside is that now (* -> TOMBSTONE) transition is confined to housekeeper thread,
          //          and that confinement become broken -- needs to investigate consequences.

          //return the page to NOT_READY_YET state, so it could be either re-tried to load, or entombed
          this.statePacked = packState(STATE_NOT_READY_YET, 0);
          //MAYBE RC: log the exception?
          this.auxDebugData = e;
          throw e;
        }
      }
    }
    return false;
  }

  /**
   * Tries t
epareForUse(final @NotNull PageContentLoader contentLoader) throws IOException 