/**
   * The <code>addNode()</code> method adds a node to this synchronization group. This method should
   * only be called before the <code>start()</code> method is called.
   *
   * @param t the simulator representing the node to add to this group
   */
  public synchronized void addNode(Simulation.Node t) {
    // if we already have this thread, do nothing
    SimulatorThread st = t.getThread();
    if (threadMap.containsKey(st)) return;

    st.setSynchronizer(this);

    // create a new synchronization event for this thread's queue
    SynchEvent event = new SynchEvent(st);
    threadMap.put(st, event);
    // insert the synch event in the thread's queue
    event.clock.insertEvent(event, period);
    goal++;
  }
  /**
   * The <code>removeNode()</code> method removes a node from this synchronization group, and wakes
   * any nodes that might be waiting on it.
   *
   * @param t the simulator thread to remove from this synchronization group
   */
  public synchronized void removeNode(Simulation.Node t) {
    // don't try to remove a thread that's not here!
    SimulatorThread st = t.getThread();
    if (!threadMap.containsKey(st)) return;
    synchronized (condition) {
      SynchEvent e = (SynchEvent) threadMap.get(st);
      e.removed = true; // just in case the thread is still running, don't let it synch
      if (e.met) meet_count--;

      if (stillWaiting(e.waitSlot)) {
        // if this wait slot hasn't happened yet, we need to decrement wait_count
        // and to decrement the number of waiters in that slot
        e.waitSlot.numWaiters--;
        wait_count--;
      }
      threadMap.remove(e);
      goal--;
      // signal any other threads (and wake waiters as necessary) but don't wait
      signalOthers();
    }
  }