package umontreal.iro.lecuyer.simprocs;
import java.util.Observable;
import umontreal.iro.lecuyer.simevents.Simulator;
import umontreal.iro.lecuyer.simevents.LinkedListStat;

/**
 * A Condition is a boolean indicator, with a list of processes  
 * waiting for the indicator to be true (when it is false).
 * A process calling {@link #waitFor waitFor} on a condition that is currently
 * false is suspended until the condition becomes true.
 * The list of waiting processes can be accessed via {@link #waitList waitList}.
 * 
 */
public class Condition extends Observable  {

   private String name;
   private LinkedListStat waitingList;
   private boolean state;
   private boolean broadcasting;
   private ProcessSimulator sim;


   /**
    * Constructs a new Condition with initial value val, linked with the default simulator.
    *  
    * @param val initial state of the condition
    * 
    * 
    */
   public Condition (boolean val)  {
      this (val, "");
   }


   /**
    * Constructs a new Condition with initial value val, linked with simulator sim.
    *  
    * @param sim current simulator of the variable
    * 
    *    @param val initial state of the condition
    * 
    * 
    */
   public Condition (ProcessSimulator sim, boolean val)  {
      this (sim, val, "");
   }


   /**
    * Constructs a new Condition with initial value val, 
    *  identifier name and linked with the default simulator.
    * 
    * @param val initial state of the condition
    * 
    *    @param name identifier or name for the condition
    * 
    * 
    */
   public Condition (boolean val, String name)  {
      super();
      try {
         ProcessSimulator.initDefault();
         this.sim = (ProcessSimulator)Simulator.getDefaultSimulator();
         waitingList = new LinkedListStat(sim);
         this.name = name;
         broadcasting = false;
         state = val;
      }
      catch (ClassCastException e) {
         throw new IllegalArgumentException("Wrong default Simulator type");
      }
   }


   /**
    * Constructs a new Condition with initial value val, 
    *  identifier name and linked with simulator sim.
    *  
    * @param sim current simulator of the variable
    * 
    *    @param val initial state of the condition
    * 
    *    @param name identifier or name for the condition
    * 
    */
   public Condition (ProcessSimulator sim, boolean val, String name)  {
      super();
      this.sim = sim;
      waitingList = new LinkedListStat(sim);
      this.name = name;
      broadcasting = false;
      state = val;
   }


   /**
    * Reinitializes this Condition by clearing up 
    *    its waiting list and resetting its state to val.
    *    The processes in this list (if any) remain in the same states.
    *  
    * @param val initial state of the condition
    * 
    * 
    */
   public void init (boolean val)  {
      waitingList.clear();
      state = val;
      if (broadcasting) {
         setChanged();
         notifyObservers (new Boolean (state));
      }
   }


   /**
    * Sets the condition to val.
    *    If val is true, all the processes waiting 
    *    for this condition now resume their execution, in the same order as
    *    they have called {@link #waitFor waitFor} for this condition.
    *    (Note that a process can never wait for more than one condition at
    *    a time, because it cannot call {@link #waitFor waitFor} while it is suspended.
    *  
    * @param val new state of the condition
    * 
    * 
    */
   public void set (boolean val)  { 
      state = val;
      if (state) {
         UserRecord record;
         while (!waitingList.isEmpty()) {
            record= waitingList.removeLast();
            record.process.resume();
         }    
      } 
      if (broadcasting) {
         setChanged();
         notifyObservers (new Boolean (val));
      }
   }


   /**
    * Returns the state (true or false) of the condition.
    *  
    * @return the current state of the condition
    * 
    */
   public boolean state()  { 
      return state;
   }


   /**
    * The executing process invoking this method
    *   must wait for this condition to be true.
    *   If it is already true, the 
    *   process continues its execution immediately
    *    Otherwise, the executing process is placed into the 
    *    {@link #waitList waitList} list for this condition and is suspended
    *    until the condition becomes true.
    * 
    */
   public void waitFor()  {
      SimProcess p = sim.currentProcess();
      if (state == true) {
         // The process can continus right away.
         if (waitingList.statSojourn() != null)
            waitingList.statSojourn().add (0.0);
         return;
      }
      else {
         // The process joins the waitingList;
         UserRecord record = new UserRecord (1, p, sim.time());
         waitingList.addLast (record);
         p.suspend();
      }
   }


   /**
    * Returns the list of {@link UserRecord}
    *    for the processes waiting for this condition.
    *  
    * @return the list of processes user records waiting for the condition
    * 
    */
   public LinkedListStat waitList()  { 
      return waitingList;
   }


   /**
    * Returns the name (or identifier) associated
    *   to this condition.
    * 
    * @return the name associated to this object
    * 
    */
   public String getName() {
      return name;
   }


   /**
    * Instructs the condition to start or stop observation broadcasting.
    *   When this is turned ON, a {@link Boolean} observation is notified to
    *   registered observers when the state of the condition changes.  This
    *   boolean gives the new state of the condition.
    * 
    * 

* Warning: Since this can reduce program performance, this should be * turned on only when there are registered observers. * * @param b true to turn broadcasting ON, false to turn it OFF * */ public void setBroadcasting (boolean b) { broadcasting = b; } }

Ads help maintain this website.