package nl.tudelft.simulation.examples.dsol.timesharedcomputer; 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.flow.Station; import nl.tudelft.simulation.dsol.logger.SimLogger; import nl.tudelft.simulation.dsol.simtime.SimTimeDouble; 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; /** * The CPU example as published in Simulation Modeling and Analysis by A.M. Law & W.D. Kelton section 1.4 and 2.4. . *

* Copyright (c) 2003-2018 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights * reserved. See for project information * https://simulation.tudelft.nl. The DSOL project is distributed under a three-clause BSD-style license, which can * be found at * https://simulation.tudelft.nl/dsol/3.0/license.html. *

* @author Peter Jacobs */ public class CPU extends Station implements Locatable { /** */ private static final long serialVersionUID = 1L; /** 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 DEVSSimulatorInterface.TimeDouble; a devs simulator */ public CPU(final DEVSSimulatorInterface.TimeDouble simulator) { super(simulator); this.fireTimedEvent(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) { this.queue.add(object); this.fireTimedEvent(QUEUE_LENGTH_EVENT, this.queue.size(), this.simulator.getSimulatorTime()); if (this.status == IDLE) { try { this.next(); } catch (SimRuntimeException exception) { SimLogger.always().error(exception); } } } /** {@inheritDoc} */ @Override protected synchronized void releaseObject(final Object object) { this.status = IDLE; this.fireTimedEvent(UTILIZATION_EVENT, 0.0, this.simulator.getSimulatorTime()); ((Job) object).getOwner().receiveObject(object); try { this.next(); } catch (SimRuntimeException exception) { SimLogger.always().error(exception); } } /** * services the next job. * @throws SimRuntimeException on simulation failure */ private void next() throws SimRuntimeException { if (this.queue.size() > 0) { this.status = BUSY; this.fireTimedEvent(UTILIZATION_EVENT, 1.0, this.simulator.getSimulatorTime()); Job job = (Job) this.queue.remove(0); this.fireTimedEvent(QUEUE_LENGTH_EVENT, this.queue.size(), this.simulator.getSimulatorTime()); if (job.getServiceTime() > QUANTUM) { job.setServiceTime(job.getServiceTime() - QUANTUM); Object[] args = {job}; this.simulator.scheduleEventAbs(this.simulator.getSimulatorTime() + QUANTUM + SWAP, this, this, "receiveObject", args); this.simulator.scheduleEventAbs(this.simulator.getSimulatorTime() + QUANTUM + SWAP, this, this, "next", null); } else { Object[] args = {job}; this.simulator.scheduleEventAbs(this.simulator.getSimulatorTime() + job.getServiceTime() + SWAP, this, this, "releaseObject", args); } } else { this.status = IDLE; this.fireTimedEvent(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); } }