code: AcquireResult acquire(AcquireInvocationKey key, boolean wait) {
          SemaphoreEndpoint endpoint = key.endpoint();
          SessionSemaphoreState state = sessionStates.get(key.sessionId());
          if (state != null && state.containsInvocation(endpoint.threadId(), key.invocationUid())) {
              return new AcquireResult(key.permits(), Collections.<AcquireInvocationKey>emptyList());
          }
  
          Collection<AcquireInvocationKey> cancelled = cancelWaitKeys(endpoint, key.invocationUid());
  
          if (!isAvailable(key.permits())) {
              if (wait) {
                  addWaitKey(endpoint, key);
              }
  
              return new AcquireResult(0, cancelled);
          }
  
          assignPermitsToInvocation(endpoint, key.invocationUid(), key.permits());
  
          return new AcquireResult(key.permits(), cancelled);
      }
docs: Assigns permits to the endpoint, if sufficient number of permits are
  available. If there are no sufficient number of permits and the second
  argument is true, a wait key is created and added to the wait queue.
  Permits are not assigned if the acquire request is a retry of
  a successful acquire request of a session-aware proxy. Permits are
  assigned again if the acquire request is a retry of a successful acquire
  request of a sessionless proxy. If the acquire request is a retry of
  an endpoint that resides in the wait queue with the same invocation uid,
  a duplicate wait key is added to the wait queue because cancelling
  the previous wait key can cause the caller to fail. If the acquire
  request is a new request of an endpoint that resides in the wait queue
  with a different invocation uid, the existing wait key is cancelled
  because it means the caller has stopped waiting for response of
  the previous invocation.