private static void dispatchEvent(LocalRegion region, InternalCacheEvent event,
      EnumListenerEvent operation) {

    CacheListener[] listeners = region.fetchCacheListenersField();
    if (event.getOperation().isCreate()) {
      if (logger.isDebugEnabled()) {
        logger.debug("invoking listeners: {}", Arrays.toString(listeners));
      }
    }
    if (listeners == null || listeners.length == 0) {
      return;
    }
    if (operation != EnumListenerEvent.AFTER_REGION_CREATE) {
      try {
        region.waitForRegionCreateEvent();
      } catch (CancelException ignore) {
        // ignore and keep going
        if (logger.isTraceEnabled()) {
          logger.trace("Dispatching events after cache closure for region {}",
              region.getFullPath());
        }
      }
    }

    if (!event.isGenerateCallbacks()) {
      return;
    }

    for (CacheListener listener : listeners) {
      if (listener != null) {
        try {
          operation.dispatchEvent(event, listener);
        } catch (CancelException ignore) {
          // ignore
        } catch (VirtualMachineError err) {
          SystemFailure.initiateFailure(err);
          // If this ever returns, rethrow the error. We're poisoned
          // now, so don't let this thread continue.
          throw err;
        } catch (Throwable t) {
          // Whenever you catch Error or Throwable, you must also
          // catch VirtualMachineError (see above). However, there is
          // _still_ a possibility that you are dealing with a cascading
          // error condition, so you also need to check to see if the JVM
          // is still usable:
          SystemFailure.checkFailure();
          logger.error("Exception occurred in CacheListener", t);
        }
      }
    }
  }
Does not throw RegionDestroyedException even if destroyed
geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java