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
21
22
23
24
25
26
27
28
29
30 public class Cpu extends FlowObject<Double> implements Locatable
31 {
32
33 private static final long serialVersionUID = 1L;
34
35
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
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
44 public static final double QUANTUM = 0.1;
45
46
47 public static final double SWAP = 0.015;
48
49
50 public static final boolean IDLE = true;
51
52
53 public static final boolean BUSY = false;
54
55
56 private boolean status = IDLE;
57
58
59 private List<Object> queue = Collections.synchronizedList(new ArrayList<Object>());
60
61
62 private OrientedPoint3d location = new OrientedPoint3d(-90, 0, 0);
63
64
65
66
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
76
77
78 public List<Object> getQueue()
79 {
80 return this.queue;
81 }
82
83
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
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
121
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
153 @Override
154 public OrientedPoint3d getLocation()
155 {
156 return this.location;
157 }
158
159
160 @Override
161 public Bounds3d getBounds()
162 {
163 return new Bounds3d(0, 0, 0);
164 }
165 }