View Javadoc
1   package nl.tudelft.simulation.examples.dsol.timesharedcomputer;
2   
3   import java.util.ArrayList;
4   import java.util.Collections;
5   import java.util.List;
6   
7   import org.djutils.draw.bounds.Bounds3d;
8   import org.djutils.draw.point.OrientedPoint3d;
9   import org.djutils.event.EventType;
10  import org.djutils.metadata.MetaData;
11  import org.djutils.metadata.ObjectDescriptor;
12  
13  import nl.tudelft.simulation.dsol.SimRuntimeException;
14  import nl.tudelft.simulation.dsol.animation.Locatable;
15  import nl.tudelft.simulation.dsol.formalisms.flow.Entity;
16  import nl.tudelft.simulation.dsol.formalisms.flow.FlowObject;
17  import nl.tudelft.simulation.dsol.simulators.DevsSimulatorInterface;
18  
19  /**
20   * The CPU example as published in Simulation Modeling and Analysis by A.M. Law & W.D. Kelton section 1.4 and 2.4. .
21   * <p>
22   * Copyright (c) 2003-2023 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
23   * for project information <a href="https://simulation.tudelft.nl/" target="_blank"> https://simulation.tudelft.nl</a>. The DSOL
24   * project is distributed under a three-clause BSD-style license, which can be found at
25   * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">
26   * https://https://simulation.tudelft.nl/dsol/docs/latest/license.html</a>.
27   * </p>
28   * @author <a href="http://www.tbm.tudelft.nl/webstaf/peterja/index.htm">Peter Jacobs </a>
29   */
30  public class Cpu extends FlowObject<Double> implements Locatable
31  {
32      /** */
33      private static final long serialVersionUID = 1L;
34  
35      /** UTILIZATION_EVENT are fired on utilization. */
36      public static final EventType UTILIZATION_EVENT = new EventType(new MetaData("UTILIZATION_EVENT",
37              "Utilization change", new ObjectDescriptor("utilization", "Current utilization", Double.class)));
38  
39      /** QUEUE_LENGTH_EVENT is fired on changes in the Queue length. */
40      public static final EventType QUEUE_LENGTH_EVENT = new EventType(new MetaData("QUEUE_LENGTH_EVENT",
41              "Queue length change", new ObjectDescriptor("queueLength", "New queue length", Integer.class)));
42  
43      /** QUANTUM is the QUANTUM of the CPU. */
44      public static final double QUANTUM = 0.1;
45  
46      /** SWAP is the swap of this cpu. */
47      public static final double SWAP = 0.015;
48  
49      /** IDLE defines the IDLE state. */
50      public static final boolean IDLE = true;
51  
52      /** BUSY defines the BUSY state. */
53      public static final boolean BUSY = false;
54  
55      /** status of the CPU. */
56      private boolean status = IDLE;
57  
58      /** queue is the queue of waiting jobs. */
59      private List<Object> queue = Collections.synchronizedList(new ArrayList<Object>());
60  
61      /** the location. */
62      private OrientedPoint3d location = new OrientedPoint3d(-90, 0, 0);
63  
64      /**
65       * constructs a new CPU.
66       * @param simulator DevsSimulatorInterface&lt;Double&gt;; a devs simulator
67       */
68      public Cpu(final DevsSimulatorInterface<Double> simulator)
69      {
70          super("CPU", simulator);
71          this.fireTimedEvent(UTILIZATION_EVENT, 0.0, simulator.getSimulatorTime());
72      }
73  
74      /**
75       * returns the queue.
76       * @return List the queue
77       */
78      public List<Object> getQueue()
79      {
80          return this.queue;
81      }
82  
83      /** {@inheritDoc} */
84      @Override
85      public void receiveEntity(final Entity<Double> entity)
86      {
87          this.queue.add(entity);
88          this.fireTimedEvent(QUEUE_LENGTH_EVENT, this.queue.size(), getSimulator().getSimulatorTime());
89          if (this.status == IDLE)
90          {
91              try
92              {
93                  this.next();
94              }
95              catch (SimRuntimeException exception)
96              {
97                  getSimulator().getLogger().always().error(exception);
98              }
99          }
100     }
101 
102     /** {@inheritDoc} */
103     @Override
104     protected synchronized void releaseEntity(final Entity<Double> entity)
105     {
106         this.status = IDLE;
107         this.fireTimedEvent(UTILIZATION_EVENT, 0.0, getSimulator().getSimulatorTime());
108         ((Job) entity).getOwner().receiveEntity(entity);
109         try
110         {
111             this.next();
112         }
113         catch (SimRuntimeException exception)
114         {
115             getSimulator().getLogger().always().error(exception);
116         }
117     }
118 
119     /**
120      * services the next job.
121      * @throws SimRuntimeException on simulation failure
122      */
123     private void next() throws SimRuntimeException
124     {
125         if (this.queue.size() > 0)
126         {
127             this.status = BUSY;
128             this.fireTimedEvent(UTILIZATION_EVENT, 1.0, getSimulator().getSimulatorTime());
129             Job job = (Job) this.queue.remove(0);
130             this.fireTimedEvent(QUEUE_LENGTH_EVENT, this.queue.size(), getSimulator().getSimulatorTime());
131             if (job.getServiceTime() > QUANTUM)
132             {
133                 job.setServiceTime(job.getServiceTime() - QUANTUM);
134                 Object[] args = {job};
135                 getSimulator().scheduleEventAbs(getSimulator().getSimulatorTime() + QUANTUM + SWAP, this, "receiveObject", args);
136                 getSimulator().scheduleEventAbs(getSimulator().getSimulatorTime() + QUANTUM + SWAP, this, "next", null);
137             }
138             else
139             {
140                 Object[] args = {job};
141                 getSimulator().scheduleEventAbs(getSimulator().getSimulatorTime() + job.getServiceTime() + SWAP, this, "releaseObject",
142                         args);
143             }
144         }
145         else
146         {
147             this.status = IDLE;
148             this.fireTimedEvent(UTILIZATION_EVENT, 0.0, getSimulator().getSimulatorTime());
149         }
150     }
151 
152     /** {@inheritDoc} */
153     @Override
154     public OrientedPoint3d getLocation()
155     {
156         return this.location;
157     }
158 
159     /** {@inheritDoc} */
160     @Override
161     public Bounds3d getBounds()
162     {
163         return new Bounds3d(0, 0, 0);
164     }
165 }