/* * DiningPhilosopherMon.java (Implements Dining Philosophers using * Monitors.) * * Written by : Nitin Jeevan Motgi (nmotgi@cs.ucf.edu) * * Implementation of Dining Philosopher using Monitors. * * Portions copyright(c) 2001 to School of Electrical Engineering and * Computer Science, UCF, Orlando. * * $Id : DiningPhilosopherMon.java v1.0.0 02/10/2001. $ * * Revision History. * 1. Created Basic Structure Nitin 02/10/2001. * 2. Documentation added. Nitin 02/10/2001. * 3. Final Documentation Check Nitin * 4. Final Variable Name Check Nitin * 5. Final Functionality Check Nitin */ import java.lang.*; import java.util.*; /***************************************************************************** * This class provides mechanism to store Philosopher ID in the Vector. It * basically extends the properties of Object to make this work. * NOTE : As this class is accessible only to this package it is written * in this file. ****************************************************************************/ class Int extends Object{ int nID; /* Stores Philosopher Id.*/ /* Default Constructor.*/ public Int(){ } public Int(int nID){ this.nID = nID; }; public int GetID(){ return nID; }/* End of GetID.*/ }/* End of Int.*/ /***************************************************************************** * This class provides synchronized mechanism to update the request queue * to pick,eat and leave the fork for a dining philosopher. ****************************************************************************/ class FCFS{ Vector FCFSQueue; /* Is the actual request Queue.*/ /* Default Constructor for the FCFS Queue.*/ public FCFS(){ FCFSQueue = new Vector(); }/* End of FCFS.*/ /* Returns the Current ID no present in the queue. The one present at [0] is one that had entered first. */ public synchronized int GetID(){ Int ID = new Int(); ID = (Int)FCFSQueue.elementAt(0); return ID.GetID(); }/* End of GetID.*/ /* Adds an ID of philosopher to the Queue. This procedure is not synchronized due to the fact that multiple people may try to update the Queue, but they are all protected at higher level from entrying into this section at same point of time.*/ public void AddToQueue(int nID){ Int ID = new Int(nID); /* Get the size of the current queue.*/ int nSize = FCFSQueue.size(); FCFSQueue.insertElementAt((Object)ID,nSize); }/* End of AddToQueue.*/ /* Removes a Philosopher ID from the Queue. This procedure is not sync. as higher level routine calling this is synchronized making is serialzable at the lower level.*/ public synchronized void RemoveFirst(){ FCFSQueue.removeElementAt(0); }/* End of RemoveFirst.*/ }/* End of FCFS.*/ /***************************************************************************** * This class simulates a higher level interface for dining philosopher * problem using monitors. This class basically collects all the request * from the philosophers to eat and puts them in the queue on FC basis. * And, the philosopher whoes ID match the one in the queue head will * eat and release the fork. So in this implementation there is only * philosopher eating at any point of time. * * NOTE : Monitor implementation requires that there should be only * one philosopher active(picking,eating and releasing). ****************************************************************************/ public class DiningPhilosopherMon{ PhilosopherMon PhilSet[]; /* Set of Philosophers @Array.*/ private FCFS Queue; /* FCFS request Queue.*/ Semaphore Event; /* Sync. for # of current Events.*/ int nEventCount; /* # of Events.*/ long lStartTime; /* @Start time of this sim.*/ long lStopTime; /* Intermediate @stop times.*/ int nPhil; /* # of Philosophers.*/ int nEvents; /* Max number of events.*/ /* This is default constructor for DiningPhilosopherMon problem.*/ public DiningPhilosopherMon(int nPhil, int nEvents, long lStartTime){ this.nPhil = nPhil; this.nEvents = nEvents; this.lStartTime = lStartTime; /* Create a Request Queue for Picking, eating and keeping the fork.*/ Queue = new FCFS(); /* Create all Philosopher needed for simulation.*/ PhilSet = new PhilosopherMon[nPhil]; /* This is used to protect the Event counter, as it is updated simultaneously by different processes.*/ Event = new Semaphore(1); /* Initialise Event count to zero for this simulation.*/ nEventCount = 0; }/* End of Constructor.*/ /* This is standard Start procedure used to create all the Philosophers and also waits till all the threads die a grace full death. It has time management facility too.*/ public void Start(){ /* Time formatter is instantiated and ready for use.*/ TimeFormat Time = new TimeFormat(); /* Print the Start time for simulation.*/ lStopTime = System.currentTimeMillis(); System.out.println("Started using Monitors at time " + Time.formatTime(lStopTime - lStartTime)); /* Create all philosophers.*/ for(int nIndex=0; nIndex < nPhil; nIndex++){ PhilSet[nIndex] = new PhilosopherMon((nIndex+1),this); PhilSet[nIndex].start(); /* Start the threads immediately.*/ }/* 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 Monitors at time " + Time.formatTime(lStopTime - lStartTime)); }/* End of Start.*/ /* Monitor Eat: This function first checks whether it is the first in in the request queue. If it is it will go ahead with picking the fork, eating and leaving the fork procedure. But, in case if it is not the one to whoes ID is in the queue it will go in the wait state till it has been notified with the one that has finished Phil Proc.*/ public void Eat(PhilosopherMon Phil){ /* Check if your ID match the one in the Queue Head, if so then go ahead and eat else wait till you are notified.*/ while(Phil.nID != Queue.GetID()){ try{ wait(); }catch(InterruptedException e){ e.printStackTrace(); } }/* End of while.*/ /* PICK UP THE FORKS PRESENT ON YOUR ADJACENT SIDES AND ATTEMPT TO EAT. Note : There is no other Philosopher in this region, as the request queue Id match allows only one philosopher to be in this region of code.*/ /* Sync. and increment the event count.*/ Event.P(); if(nEventCount == nEvents) Phil.SetEndCondition(false); else nEventCount++; Event.V(); }/* End of Eat.*/ /* This is a request by philosopher to acquire lock. It will add the Philosopher ID in the FCFS Queue. This function provides high level sync. mechanism for multiple request handling, hence, making the lower levels of request serializable.*/ public synchronized void AcquireLock(PhilosopherMon Phil){ Queue.AddToQueue(Phil.nID); }/* End of AcquireLock.*/ /* This basically releases the fork in the hands of philosopher and also removes the Philosopher ID from the queue as its request has be completed.*/ public synchronized void ReleaseLock(PhilosopherMon Phil){ /* RELEASE THE FORKS ACQUIRED FROM THE ADJACENT SIDE.*/ /* Remove from the Queue as this request has been processed.*/ Queue.RemoveFirst(); /* Notify all the philosophers who are waiting to for their trun to pick fork, eat food and leave fork.*/ notifyAll(); }/* End of Think.*/ }/* End of DiningPhilosopherMon.*/