// Make thread wait on the object until being notified by another thread.
  protected final void wait(Component host_, Object o_) {
    // if (nextTask != null) _semanticsError("wait(Object)");
    // looking for LockPack in host
    LockPack p_ = lookforLock(host_, o_);

    String old_ = state;
    setState(State_WAITING);
    synchronized (o_) {
      // Records the status if the thread holds the lock.
      if (waitPack == null) waitPack = new WaitPack();
      waitPack.target = p_.target;
      if (p_.holder == this) {
        waitPack.counter = p_.counter;
        // unlock(host_, o_, true/* release all grabs */);
        // below is copied from unlock()
        synchronized (p_) {
          p_.holder = null;
          if (p_.lockReqCount == 0) p_.counter = 0;
          else {
            p_.counter = -1;
            // p_.counter is not zero, see Note 1 above
            p_.lockReqCount--;
            synchronized (aruntime) {
              if (aruntime.getWorkforce()) {
                p_.notify(); // dont know who's going to wake up
                aruntime.nthreadsWaiting--;
              } else aruntime.newTask(Task.createNotify(p_), this);
            }
          }
        }
      }
      p_.waitCount++;

      // waited to be notified
      _sleepOn(o_, State_WAITING, null);

      if (isOrphan()) throw new WorkerThreadInterruptedException("Orphan thread");

      // _awakened();

      // re-grabbing the lock if necessary.
      if (waitPack.counter > 0) {
        synchronized (p_) {
          if (p_.holder != null) lock(host_, p_.target);
          else {
            p_.holder = this;
            p_.counter = waitPack.counter;
          }
        }
      }
    }

    if (p_ != null) {
      waitPack.counter = 0;
      waitPack.target = null;
    }
  }
  protected final void lock(Component host_, Object o_) {
    // looking for LockPack in host
    LockPack p_ = lookforLock(host_, o_);

    // No need to grab p_'s monitor if thread is already the lock holder.
    if (p_.holder == this) {
      p_.counter++;
      return;
    }

    String old_ = state;
    synchronized (p_) {
      // the lock holder may be an orphan from previous run
      // if (p_.holder == null || p_.holder.isOrphan()) {
      if (p_.counter == 0 || (p_.holder != null && p_.holder.isOrphan())) {
        // thread becomes the lock holder
        p_.holder = this;
        p_.counter = 1;
        return;
      }

      // if (nextTask != null) _semanticsError("lock(Object)");

      // Else:
      // 1. add thread itself to the waiting queue;
      // 2. going into sleep;
      // 3. getting the lock after awake;

      // p_.qWaiting.enqueue(this);
      p_.lockReqCount++;
      if (waitPack == null) waitPack = new WaitPack();
      waitPack.target = p_.target; // for debugging only
      _sleepOn(p_, State_LOCKING, null); // wait for lock
      waitPack.target = null;
      // p_.qWaiting.remove(this);
      if (isOrphan()) {
        p_.notify();
        return;
      }
      p_.holder = this;
      p_.counter = 1;
      // _awakened();
    }
  }