package nl.tudelft.simulation.examples.dsol.timesharedcomputer; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.media.j3d.Bounds; import nl.tudelft.simulation.dsol.SimRuntimeException; import nl.tudelft.simulation.dsol.animation.Locatable; import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEvent; import nl.tudelft.simulation.dsol.formalisms.flow.Station; import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface; import nl.tudelft.simulation.event.EventType; import nl.tudelft.simulation.language.d3.BoundingBox; import nl.tudelft.simulation.language.d3.CartesianPoint; import nl.tudelft.simulation.language.d3.DirectedPoint; import nl.tudelft.simulation.logger.Logger; /** * The CPU example as published in Simulation Modeling and Analysis by A.M. Law & W.D. Kelton section 1.4 and 2.4.
* (c) copyright 2003 Delft University of Technology , the Netherlands.
* See for project information www.simulation.tudelft.nl
* License of use: General Public License (GPL) , no warranty
* @version 2.0 21.09.2003
* @author Peter Jacobs */ public class CPU extends Station implements Locatable { /** UTILIZATION_EVENT are fired on utilization. */ public static final EventType UTILIZATION_EVENT = new EventType("UTILIZATION_EVENT"); /** QUEUE_LENGTH_EVENT is fired on changes in the Queue length. */ public static final EventType QUEUE_LENGTH_EVENT = new EventType("QUEUE_LENGTH_EVENT"); /** QUANTUM is the QUANTUM of the CPU */ public static final double QUANTUM = 0.1; /** SWAP is the swap of this cpu. */ public static final double SWAP = 0.015; /** IDLE defines the IDLE state. */ public static final boolean IDLE = true; /** BUSY defines the BUSY state. */ public static final boolean BUSY = false; /** status of the CPU */ private boolean status = IDLE; /** queue is the queue of waiting jobs. */ private List queue = Collections.synchronizedList(new ArrayList()); /** the location. */ private DirectedPoint location = new DirectedPoint(new CartesianPoint(-90, 0, 0)); /** * constructs a new CPU. * @param simulator a devs simulator * @throws RemoteException on network failure */ public CPU(final DEVSSimulatorInterface.TimeDouble simulator) throws RemoteException { super(simulator); this.fireEvent(UTILIZATION_EVENT, 0.0, simulator.getSimulatorTime()); } /** * returns the queue * @return List the queue */ public List getQueue() { return this.queue; } /** {@inheritDoc} */ @Override public void receiveObject(final Object object) { try { this.queue.add(object); this.fireEvent(QUEUE_LENGTH_EVENT, this.queue.size(), this.simulator.getSimulatorTime()); if (this.status == IDLE) { try { this.next(); } catch (SimRuntimeException exception) { logger.warn("receiveObject", exception); } } } catch (RemoteException remoteException) { logger.warn("receiveObject", remoteException); } } /** {@inheritDoc} */ protected void releaseObject(final Object object) throws RemoteException { this.status = IDLE; this.fireEvent(UTILIZATION_EVENT, 0.0, this.simulator.getSimulatorTime()); ((Job) object).getOwner().receiveObject(object); try { this.next(); } catch (SimRuntimeException exception) { logger.warn("receiveObject", exception); } } /** * services the next job * @throws RemoteException on network failure * @throws SimRuntimeException on simulation failure */ private void next() throws RemoteException, SimRuntimeException { if (this.queue.size() > 0) { this.status = BUSY; this.fireEvent(UTILIZATION_EVENT, 1.0, this.simulator.getSimulatorTime()); Job job = (Job) this.queue.remove(0); this.fireEvent(QUEUE_LENGTH_EVENT, this.queue.size(), this.simulator.getSimulatorTime()); if (job.getServiceTime() > QUANTUM) { job.setServiceTime(job.getServiceTime() - QUANTUM); Object[] args = {job}; this.simulator.scheduleEvent(new SimEvent(this.simulator.getSimulatorTime() + QUANTUM + SWAP, this, this, "receiveObject", args)); this.simulator.scheduleEvent(new SimEvent(this.simulator.getSimulatorTime() + QUANTUM + SWAP, this, this, "next", null)); } else { Object[] args = {job}; this.simulator.scheduleEvent(new SimEvent(this.simulator.getSimulatorTime() + job.getServiceTime() + SWAP, this, this, "releaseObject", args)); } } else { this.status = IDLE; this.fireEvent(UTILIZATION_EVENT, 0.0, this.simulator.getSimulatorTime()); } } /** {@inheritDoc} */ @Override public DirectedPoint getLocation() { return this.location; } /** {@inheritDoc} */ @Override public Bounds getBounds() { return new BoundingBox(0, 0, 0); } }