/*
 * DiningPhilosopher.java (Implements DP using Semaphores.)
 *
 * Written by : Nitin Jeevan Motgi (nmotgi@cs.ucf.edu)
 *
 * This class implements dining philosopher problem using semaphores.
 * By using semaphore we can achieve some extent of concurrency that
 * is if in case there are 5 philosophers who are on the table 1 and 
 * 4 philosophers can simultaneously without problems.
 *
 * Portions copyright(c) 2000 to School of Electrical Engineering and
 * Computer Science, UCF, Orlando.
 *
 * Use and distribution of this source code are strictly governed by
 * terms and conditions set by the authors.
 *
 * $Id : DiningPhilosopher.java, v2.0.1, 02/07/2001.
 *
 * Revision History.
 * 1. Created Basic Structure           Nitin           02/09/2001.                  
 * 2. Documentation added               Nitin           02/09/2001.
 * 3. Final Documentation Check         Nitin           
 * 4. Final variable Name Check         Nitin           
 * 5. Final Functionality Check         Nitin
*/

import java.lang.*;

/*****************************************************************************
 * DiningPhilosopher
 * Description : Implements Dining Philosophers using Semaphores.
 * Functions   : 
 * 1. public DiningPhilosopher(int nPhil, int nEvents, long lStartTime)
 * 2. public void Start()
 * 3. public void Eat(Philosopher Phil) and
 * 4. public void Think(Philosopher Phil)
 ****************************************************************************/
public class DiningPhilosopher{
  Fork ForkSet[];               /* Set of Forks that act as semaphores.*/
  Philosopher PhilSet[];        /* Set of Philosophers.*/
  Semaphore Event;              /* To Keep track and Synch of events.*/
  int nEventCount;
  long lStartTime;              /* Start of this experiment.*/
  long lStopTime;               /* End of this experiment.*/
  int nPhil;                    /* Max no of Philosophers.*/
  int nEvents;                  /* Max no of Events.*/

  /* Default Constructor.*/
  public DiningPhilosopher(int nPhil, int nEvents, long lStartTime){
    this.nPhil = nPhil;
    this.nEvents = nEvents;
    this.lStartTime = lStartTime;
    
    /* Create all Forks needed for simulation.*/
    ForkSet = new Fork[nPhil];
    /* Create all Philosopher needed for simulation.*/
    PhilSet = new Philosopher[nPhil];

    for(int nIndex=0; nIndex < nPhil; nIndex++){
     ForkSet[nIndex] = new Fork();
    }/* End of DiningPhilosopher.*/

    Event = new Semaphore(1);
    nEventCount = 0;
  }/* End of Constructor.*/

  /* Starts the Philosopher Threads. */
   public void Start(){
    TimeFormat Time = new TimeFormat();

    lStopTime = System.currentTimeMillis();
    System.out.println("Started using Semaphores at time " + 
                        Time.formatTime(lStopTime - lStartTime));

    for(int nIndex=0; nIndex < nPhil; nIndex++){
     PhilSet[nIndex] = new Philosopher(ForkSet[nIndex%nPhil],
                                       ForkSet[(nIndex+1)%nPhil],
                                       (nIndex+1),
                                       this);
     PhilSet[nIndex].start();
    }/* End of For.*/

    /* Wait till all the Philosophers die.*/
    boolean bAllDead = false;
    while(bAllDead == false){
     bAllDead = true;
     for(int nIndex=0; nIndex < nPhil; nIndex++){
      if(PhilSet[nIndex].isAlive() == true) bAllDead = false;
     }/* End of for.*/
    }/* End of while.*/

    lStopTime = System.currentTimeMillis();
    System.out.println("Completed using Semaphores at time " + 
                        Time.formatTime(lStopTime - lStartTime));


   }/* End of Start.*/

  /* Eating Mechanism.*/
  public void Eat(Philosopher Phil){
    Phil.left.Take();
    Phil.right.Take();
    Event.P();
    if(nEventCount == nEvents) Phil.SetEndCondition(false);
    else nEventCount++;
    Event.V();
  }/* End of Eat.*/

  /* Thinking Mechanism. */
  public void Think(Philosopher Phil){
    Phil.left.Leave();
    Phil.right.Leave();
  }/* End of Think.*/
}/* End of DiningPhilosopher.*/




