/**
   * The <code>waitForNeighbors()</code> method is called from within the execution of a node when
   * that node needs to wait for its neighbors to catch up to it in execution time. The node will be
   * blocked until the other nodes in other threads catch up in global time.
   */
  public void waitForNeighbors(long time) {

    // get the current simulator thread
    SimulatorThread thread = (SimulatorThread) Thread.currentThread();
    SynchEvent event = (SynchEvent) threadMap.get(thread);
    // if the current thread is not in the synchronizer, do nothing
    if (event == null) return;

    WaitSlot w;
    synchronized (condition) {
      // allocate a wait slot for this thread
      w = insertWaiter(event, time);
      // check for other waiters and wake them if necessary
      WaitSlot h = checkWaiters();
      // if we were at the head and just woken up, we can just return
      if (w == h) return;
    }

    // falling through means that we are either not at the head
    // or that not all threads have performed a meet or a wait
    try {
      // we must grab the lock for this wait slot
      synchronized (w) {
        // check for intervening wakeup between dropping global lock and taking local lock
        if (w.shouldWait) w.wait();
      }
    } catch (InterruptedException e) {
      throw Util.unexpected(e);
    }
  }
 private WaitSlot insertAfter(WaitSlot prev, WaitSlot w) {
   if (prev != null) {
     w.next = prev.next;
     prev.next = w;
   } else {
     waitSlotList = w;
   }
   return w;
 }
  protected WaitSlot checkWaiters() {
    // have all threads reached either a meet or a wait?
    if (wait_count + meet_count < goal) return null;

    // are there any waiters at all?
    if (waitSlotList == null) return null;

    // there is a ready wait slot, wake those threads waiting on it
    WaitSlot h = waitSlotList;
    // move the wait list ahead to the next link
    waitSlotList = h.next;
    synchronized (h) {
      // notify the threads waiting on this wait slot
      h.shouldWait = false;
      h.notifyAll();
    }
    // reduce the wait count by the number of waiters in this slot
    wait_count -= h.numWaiters;
    return h;
  }