@Override
    public synchronized void memberDeparted(DistributionManager distributionManager,
        InternalDistributedMember id, boolean crashed) {
      if (destroyed) {
        return;
      }
      if (members != null) {
        members.remove(id);
      }
      if (members == null && hasListener()) {
        RegionEventImpl event =
            new RegionEventImpl(DistributedRegion.this, Operation.REGION_CLOSE, null, true, id);
        if (crashed) {
          dispatchListenerEvent(EnumListenerEvent.AFTER_REMOTE_REGION_CRASH, event);
        } else {
          // @todo darrel: it would be nice to know if what actual op was done
          // could be close, local destroy, or destroy (or load snap?)
          if (DestroyRegionOperation.isRegionDepartureNotificationOk()) {
            dispatchListenerEvent(EnumListenerEvent.AFTER_REMOTE_REGION_DEPARTURE, event);
          }
        }
      }
      if (getMembershipAttributes().hasRequiredRoles()) {
        Set<Role> newlyMissingRoles = Collections.emptySet();
        synchronized (missingRequiredRoles) {
          Set<Role> roles = id.getRoles();
          for (Role role : roles) {
            if (getMembershipAttributes().getRequiredRoles().contains(role)
                && !basicIsRoleInRegionMembership(role)) {
              if (newlyMissingRoles.isEmpty()) {
                newlyMissingRoles = new HashSet<>();
              }
              newlyMissingRoles.add(role);
              if (members == null && !isMissingRequiredRoles) {
                isMissingRequiredRoles = true;
                getCachePerfStats().incReliableRegionsMissing(1);
                if (getMembershipAttributes().getLossAction().isAllAccess()) {
                  getCachePerfStats().incReliableRegionsMissingFullAccess(1); // rahul
                } else if (getMembershipAttributes().getLossAction().isLimitedAccess()) {
                  getCachePerfStats().incReliableRegionsMissingLimitedAccess(1);
                } else if (getMembershipAttributes().getLossAction().isNoAccess()) {
                  getCachePerfStats().incReliableRegionsMissingNoAccess(1);
                }

                boolean async = lostReliability(id, newlyMissingRoles);
                if (async) {
                  destroyed = true;
                }
              }
            }
          }
          if (!destroyed) {
            missingRequiredRoles.addAll(newlyMissingRoles);
            // any number of threads may be waiting on missingRequiredRoles...
            missingRequiredRoles.notifyAll();
          }
        }
        if (!destroyed && members == null && hasListener()) {
          if (!newlyMissingRoles.isEmpty()) {
            // fire afterRoleLoss event
            RoleEventImpl relEvent = new RoleEventImpl(DistributedRegion.this,
                Operation.REGION_CLOSE, null, true, id, newlyMissingRoles);
            dispatchListenerEvent(EnumListenerEvent.AFTER_ROLE_LOSS, relEvent);
          }
        }
      }
    }
called when membership listeners are added after region creation
geode-core/src/main/java/org/apache/geode/internal/cache/DistributedRegion.java