/**
   * Expert: decreases the refCount of this IndexReader instance. If the refCount drops to 0, then
   * this reader is closed. If an exception is hit, the refCount is unchanged.
   *
   * @throws IOException in case an IOException occurs in doClose()
   * @see #incRef
   */
  public final void decRef() throws IOException {
    // only check refcount here (don't call ensureOpen()), so we can
    // still close the reader if it was made invalid by a child:
    if (refCount.get() <= 0) {
      throw new AlreadyClosedException("this IndexReader is closed");
    }

    final int rc = refCount.decrementAndGet();
    if (rc == 0) {
      closed = true;
      Throwable throwable = null;
      try {
        doClose();
      } catch (Throwable th) {
        throwable = th;
      } finally {
        try {
          reportCloseToParentReaders();
        } finally {
          notifyReaderClosedListeners(throwable);
        }
      }
    } else if (rc < 0) {
      throw new IllegalStateException(
          "too many decRef calls: refCount is " + rc + " after decrement");
    }
  }
 private void reportCloseToParentReaders() {
   synchronized (parentReaders) {
     for (IndexReader parent : parentReaders) {
       parent.closedByChild = true;
       // cross memory barrier by a fake write:
       parent.refCount.addAndGet(0);
       // recurse:
       parent.reportCloseToParentReaders();
     }
   }
 }