docs: void acquire(Locker locker, int requestedMode, boolean wait)
                      throws InterruptedException,
                      LockException
      {
          Waiter waiter = null;
  
          synchronized (this) {
  
              //-----------------------------------------
              // If there are no holders or waiters then
              // acquisition is immediately successful
              //-----------------------------------------
  
              if (numUsers == 0) {
                  holders.put(locker, locker);
                  mode = requestedMode;
                  numUsers++;
                  return;
              }
  
              //------------------------------------------------
              // If lock already held then acquisition succeeds
              //------------------------------------------------
  
              if (holders.get(locker) != null) {
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, "Lock currently held by locker");
                  }
                  return;
              }
  
              //------------------------------------------------------
              // Check for conflict, if requested mode is compatible
              // with held mode and no one is waiting then grant lock
              //------------------------------------------------------
  
              if (mode == LockManager.SHARED) {
                  if (requestedMode == LockManager.SHARED) {
                      if (waiters.size() == 0) {
                          holders.put(locker, locker);
                          numUsers++;
                          return;
                      }
                  }
              }
  
              //-------------------------------------------
              // Conflict: check if we are already waiting,
              // and if we are then upgrade our lock mode
              // if necessary
              //-------------------------------------------
  
              Waiter currWaiter = (Waiter) waiters.get(locker);
  
              if (currWaiter != null) {
                  if (currWaiter.mode != requestedMode) {
                      if (lockMgr.detectDeadlock(locker, this, requestedMode)) {
                          throw new DeadlockException();
                      }
                      if (requestedMode == LockManager.EXCLUSIVE) {
                          currWaiter.mode = LockManager.EXCLUSIVE;
                      }
                  }
                  waiter = currWaiter;
              } else {
  
                  //------------------------------------------
                  // Not currently waiting, add to wait queue
                  //------------------------------------------
  
                  if (lockMgr.detectDeadlock(locker, this, requestedMode)) {
                      throw new DeadlockException();
                  }
                  waiter = new Waiter(this, locker, requestedMode);
                  waiters.put(locker, waiter);
                  lockMgr.waitEvent(waiter);
                  numUsers++;
                  waitQ.addElement(waiter);
              }
          }
  
          //------------------------------------------------------------
          // Note, at this point we have added new waiter to lock, but
          // lock is NOT held on behalf of caller. Lock has effectively
          // been reserved for waiter.
          //------------------------------------------------------------
  
          if (!wait) {
              return;
          }
  
          //----------------------------------------------------------------
          // Sleep current thread outside of scope of the synchronization
          // lock on this instance
          //----------------------------------------------------------------
  
          synchronized (waiter) {
  
              //-----------------------------------------------------------
              // Check to make sure lock wasn't released or granted while
              // we were waiting to acquire synchronization lock
              //-----------------------------------------------------------
  
              if (waiter.released) {
                  throw new LockReleasedException();
              }
  
              if (waiter.theLock.holders.get(waiter.locker) == null) {
  
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, "waiting for lock",
                               new Object[] { lockName, locker,
                                             LockManager.modeStrs[mode] });
                  }
                  waiter.wait();
  
                  if (waiter.released) {
                      throw new LockReleasedException();
                  }
              }
          }
  
      }