docs: public ConsumerKey attachConsumerPoint(
      ConsumerPoint consumerPoint,
      SelectionCriteria criteria,
      SIBUuid12 connectionUuid,
      boolean readAhead,
      boolean forwardScanning,
      JSConsumerSet consumerSet) throws SIDestinationLockedException, SISelectorSyntaxException, SIDiscriminatorSyntaxException, SINotPossibleInCurrentConfigurationException, SIResourceException
    {
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
        SibTr.entry(this,tc, "attachConsumerPoint",
          new Object[]{consumerPoint,
                       criteria,
                       connectionUuid,
                       new Boolean(readAhead),
                       new Boolean(forwardScanning),
                       consumerSet});
      
      ConsumerKey returnKey = null;
      
      // There are a few times that we're unable to accept new consumers, e.g. forcing a
      // flush or changing cardinality. None of these events should last very long so
      // we just try again a few times, if it's still in this state then something else has
      // probably gone wrong so we bomb out. We obviously can't hold a lock while we're
      // retrying.
      int chances = 5;
      boolean repeat = true;
      while(repeat)
      {
        repeat = false;
        
        synchronized (consumerPoints)
        {
          if (!_currentReachability)
          { // don't allow an attachment if DME is not reachable or a CardinalityChange is in progress or a forced flush
            // is in progress
            // throw exception
            SIResourceException e = new SIResourceException(
              nls.getFormattedMessage("ANYCAST_STREAM_UNAVAILABLE_CWSIP0471",
                                      new Object[]{getDestName(), SIMPUtils.getMENameFromUuid(getLocalisationUuid().toString())},
                                      null));
            SibTr.exception(tc, e);
            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.exit(tc, "attachConsumerPoint", e);
            throw e;
          }
          else if (_cardinalityOne)
          { // enforce cardinality
            if (consumerPoints.size() != 0)
            {
              // throw exception
              SIResourceException e = new SIResourceException(
                nls.getFormattedMessage("CONSUMERCARDINALITY_LIMIT_REACHED_CWSIP0472",
                                        new Object[]{getDestName(), getLocalisationUuid().toString()},
                                        null));
              SibTr.exception(tc, e);
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                SibTr.exit(tc, "attachConsumerPoint", e);
              throw e;
            }
          }
          // The stream is in a funny state, try again in a few milliseconds
          else if (_cardinalityChange || _forceFlushInProgress)
          {
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
              SibTr.debug(tc, "Unable to attach at this point " + _cardinalityChange + ":" +
                              _forceFlushInProgress);
            repeat = true;
          }
          
          // Work out how long we should wait for a response from the DME based on whether 
          // we are gathering or not
          long responseTimeout = 0;
          if (consumerPoint.isGatheringConsumer())
            responseTimeout = SIMPConstants.GATHERING_ANYCAST_RESPONSE_INTERVAL; // 10 seconds
          else
            responseTimeout = SIMPConstants.ANYCAST_RESPONSE_INTERVAL; // 5 minutes
          
          // do this in sync block to prevent two concurrent attachConsumerPoints from succeeding
          // when cardinalityOne, and to ensure that reachability changes are notified.
          if(_aih.consumerAttaching(responseTimeout))
          {
            returnKey = super.attachConsumerPoint(consumerPoint,
                criteria,
                connectionUuid,
                readAhead,
                forwardScanning,
                consumerSet);
          }
          else
          {
            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
              SibTr.debug(tc, "Unable to attach at this point, flush work in progress");
            repeat = true;
          }
  
          // If we're unable to attach at this exact point, but there's a probability that
          // we will in a split second, we sleep for a short time and try again (unless it's
          // time to give up).
          if(repeat)
          {
            if(chances > 0)
            {
              try
              {
                // Release the consumerPoints lock while we're waiting
                consumerPoints.wait(100);
              }
              catch (InterruptedException e)
              {
                // No FFDC code needed
              }
              chances--;
            }
            else
            {
              // throw exception, should be rare
              SIResourceException e =
                new SIResourceException(
                  nls.getFormattedMessage(
                    "ANYCAST_STREAM_NOT_FLUSHED_CWSIP0512",
                    new Object[]{_messageProcessor.getMessagingEngineName(), _destName},
                    null));
              SibTr.exception(tc, e);
              
              // As we don't expect this to have taken so long, we FFDC just in case
              // someone is interested
              FFDCFilter.processException(e,
                                          "com.ibm.ws.sib.processor.impl.RemoteConsumerDispatcher.attachConsumerPoint",
                                          "1:445:1.97.2.21",
                                          this);
              
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                SibTr.exit(tc, "attachConsumerPoint", e);
              
              throw e;
            }
          } // repeat
        } // end synchronized (consumerPoints)
      } // while
      
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
        SibTr.exit(tc, "attachConsumerPoint", returnKey);
      return returnKey;
    }