docs: protected JSLocalConsumerPoint processQueuedMsgs(boolean isolatedRun) throws SIResourceException, SISessionDroppedException
      {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.entry(tc, "processQueuedMsgs", new Object[] { this, Boolean.valueOf(isolatedRun) });
  
          JSLocalConsumerPoint actualConsumer = this;
          boolean started = true;
          _drainQueue = true;
          long timeout = INFINITE_WAIT;
  
          if (isolatedRun)
          {
              timeout = NO_WAIT;
          }
  
          //need to count the number of messages we get so that we don't exceed the maxBatchSize
          int numOfMsgs = 0;
  
          // The following value indicates that we are an isolatedRun and that we need to perform
          // a wait on a message.
          boolean isolatedWait = false;
  
          _transferredConsumer = null;
  
          // Java doesn't like giving up control of a thread once its got it. We repeatedly
          // take and release the consumer lock here but there may be others trying to stop
          // us processing the entire queue before we stop. If they are we can at least try
          // a yield, that may give the JVM the hint.
          if (_lockRequested)
          {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                  SibTr.debug(tc, "Yield requested");
              Thread.yield();
          }
  
          ConsumableKey attachedKey = null;
  
          // We don't hold the LCP lock here (just like in put()) but we do hold the asynch lock
          // so we're protected against the keyGroup being unset underneath us
          if ((_keyGroup != null))
              _keyGroup.lock();
  
          try
          {
              // We need the consumer lock so that we can set the consumer as
              // ready or not (and check the close state).
              this.lock(); // Short held lock - checking/changing state and locking msgs
              try
              {
                  // If the consumer has been closed or is currently suspended (e.g. has hit the
                  // maxActiveMEssage limit) then don't go round again looking for another message.
                  // If we're suspended we'll be resumed once the reason for suspension has been
                  // sorted.
                  if (_closed || isSuspended() || !_asynchConsumerRegistered)
                  {
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                          SibTr.debug(tc, "processQueuedMsgs", "Closed:" + _closed + " Suspended:" + _consumerSuspended);
  
                      started = false;
                      _drainQueue = false;
                  }
                  // When we're counting active messages there's a possibility that a runAsynchConsumer
                  // thread will be dispatched due to a resumeConsumer while a producer thread is just
                  // about to attach a message to us (there is a legit window where the ConsumerDispatcher
                  // can think we're 'ready' even when we're not). If the attach gets in between the checkin
                  // processAttachedMsgs() (called just before this) and here then we've got to realise it
                  // and process the attached message first
                  else
                  {
                      if (_keyGroup != null)
                      {
                          // Look for a message attached to the group, but don't process them under this lock
                          attachedKey = _keyGroup.getAttachedMember();
                      }
                      // When we're counting active messages there's a possibility that a runAsynchConsumer
                      // thread will be dispatched due to a resumeConsumer while a producer thread is just
                      // about to attach a message to us (there is a legit window where the ConsumerDispatcher
                      // can think we're 'ready' even when we're not). If the attach gets in between the checkin
                      // processAttachedMsgs() (called just before this) and here then we've got to realise it
                      // and process the attached message first
                      else if (_msgAttached)
                      {
                          // Process the attached message, but not under this lock
                          attachedKey = _consumerKey; // We're not in a group so it must be for us
                      }
  
                      // If we don't have an attached message, check the queue
                      if ((attachedKey == null) && _drainQueue)
                      {
                          numOfMsgs = lockMessages(isolatedRun);
                          if (_transferredConsumer != null)
                              actualConsumer = _transferredConsumer;
  
                          // If we get to this point and we're still ready then we are basically
                          // waiting for messages to arrive, when remote from the destination the CD
                          // needs to know when we are doing this by us calling waiting().
                          // As we are an async consumer we will wait indefinitely for a message
                          // NB. This doesn't actually cause this thread to wait!
                          if ((_ready && (_keyGroup == null)) || (_keyGroup != null) && (_keyGroup.isGroupReady()))
                          {
                              timeout = _consumerKey.waiting(timeout, true);
                              isolatedWait = _isolatedRun;
                          }
                          else if (_gatherMessages) // DID get a msg - but need to consider other partitions...
                              // If we are a gatherer then we still want to call waiting to perform refills.
                              // Dont want to set the timeout though as this will cause us to wait.
                              _consumerKey.waiting(timeout, true);
                      }
                  }
              } // sync
              finally
              {
                  this.unlock();
              }
          } finally
          {
              if (_keyGroup != null)
                  _keyGroup.unlock();
          }
  
          // Now we've released the lock, process the attached message and exit, forcing
          // runAsynchConsumer to go round the loop again.
          if (attachedKey != null)
          {
              // If we found one, process it
              ((JSLocalConsumerPoint) attachedKey.getConsumerPoint()).processAttachedMsgs();
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                  SibTr.exit(tc, "processQueuedMsgs", actualConsumer);
              return (JSLocalConsumerPoint) attachedKey.getConsumerPoint();
          }
  
          // If the session has been closed but we managed to lock one
          // or more messages we must have taken the asynchConsumer lock
          // before the close() method. Therefore, when we release it here
          // the close() method will eventually aquire it and unlock all
          // locked messages so we don't need to do anything here.
          // That's the theory anyway.
          if (started)
          {
              //if we got at least one message
              if ((numOfMsgs > 0) && (actualConsumer == this))
              {
                  //initiate the callback
                  _asynchConsumer.processMsgs(_allLockedMessages, _consumerSession);
  
                  // Clean up the LME
                  _allLockedMessages.resetCallbackCursor();
  
                  // Go back round in case more came in while we were busy
                  if (!isolatedRun)
                      _drainQueue = true;
                  else
                      _drainQueue = false;
              }
          }
  
          // If a message was found on the queue for a different member of the ordering group
          // we process that message now on the correct consumer.
          if (actualConsumer != this)
          {
              actualConsumer.processTransferredMsg();
          }
  
          // If we're performing a remote or gathering isolated run but failed to find a message
          // at this ME we need to wait for the request to return from the DME. We do it
          // here under the asynch lock so that no-one else can try anything else on
          // this session till we've finished.
          if (isolatedWait)
          {
              this.lock();
              try
              {
                  // It's just possible a message arrived before we took this
                  // lock, if so skip the wait.
                  if (!_msgAttached)
                  {
                      // The RCD will have calculated an appropriate period
                      // for this command to take to complete, use that here to
                      // block the thread for at most that period. If a message
                      // is returned in that time this thread will be notified.
                      try
                      {
                          //wait for the specified time
                          if (timeout == LocalConsumerPoint.INFINITE_WAIT)
                              _waiter.await();
                          else
                              _waiter.await(timeout, TimeUnit.MILLISECONDS);
                      } catch (InterruptedException e)
                      {
                          // No FFDC code needed
                          // No message arrived so return null
                      }
                  }
  
                  //we're not ready for any more messages
                  unsetReady();
  
                  // We've finished this isolated run request
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                      SibTr.debug(tc, "Finished isolatedrun request set to FALSE");
                  _isolatedRun = false;
              } finally
              {
                  this.unlock();
              }
  
              // If we had a message delivered while we were waiting, process it
              processAttachedMsgs();
          }
  
          // After processing messages for this consumer we better check to see
          // if someone else is waiting for the lock
          if (_externalConsumerLock != null)
          {
              // lockMessages() may already have spotted the yield request
              if (!_interruptConsumer)
                  _interruptConsumer = _externalConsumerLock.isLockYieldRequested();
          }
  
          // If we're no longer draining the queue (maybe we've been stopped or
          // ran out of messages) indicate this to the caller by returning null
          if (!_drainQueue)
              actualConsumer = null;
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.exit(tc, "processQueuedMsgs", actualConsumer);
  
          return actualConsumer;
      }