-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSimulator.java
291 lines (241 loc) · 8.11 KB
/
Simulator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
package round_robin;
import java.lang.*;
import java.util.LinkedList;
import java.util.function.Consumer;
/**
* The main class of the P3 exercise. This class is only partially complete.
*/
public class Simulator
{
/** Process queues */
private LinkedList<Process> memoryQueue = new LinkedList<>();
private LinkedList<Process> cpuQueue = new LinkedList<>();
private LinkedList<Process> ioQueue = new LinkedList<>();
/** The queue of events to come */
private EventQueue eventQueue = new EventQueue();
/** Reference to the statistics collector */
private Statistics statistics = new Statistics();
private volatile Consumer<Long> onTimeStep = null;
private volatile Consumer<Long> onEventHandled = null;
/** Reference to the memory unit */
private Memory memory;
/** Reference to the CPU */
private Cpu cpu;
/** Reference to the I/O device */
private Io io;
/** The global clock */
private long clock;
/** The length of the simulation */
private long simulationLength;
/** The average length between process arrivals */
private long avgArrivalInterval;
// Add member variables as needed
/**
* Constructs a scheduling simulator with the given parameters.
* @param memorySize The size of the memory.
* @param maxCpuTime The maximum time quant used by the RR algorithm.
* @param avgIoTime The average length of an I/O operation.
* @param simulationLength The length of the simulation.
* @param avgArrivalInterval The average time between process arrivals.
*/
public Simulator(long memorySize, long maxCpuTime, long avgIoTime, long simulationLength, long avgArrivalInterval) {
this.simulationLength = simulationLength;
this.avgArrivalInterval = avgArrivalInterval;
this.statistics = new Statistics();
memory = new Memory(memoryQueue, memorySize, statistics);
cpu = new Cpu(cpuQueue, maxCpuTime, statistics);
io = new Io(ioQueue, avgIoTime, statistics);
memoryQueue.add(new Process(memorySize, avgIoTime));
clock = 0;
// Add code as needed
}
/**
* Starts the simulation. Contains the main loop, processing events.
* This method is called when the "Start simulation" button in the
* GUI is clicked.
*/
public void simulate() {
System.out.print("Simulating...");
// Genererate the first process arrival event
eventQueue.insertEvent(new Event(Event.NEW_PROCESS, 0));
// Update statistics
statistics.nofCreatedProcesses++;
// Process events until the simulation length is exceeded:
while (clock < simulationLength && !eventQueue.isEmpty()) {
// Find the next event
Event event = eventQueue.getNextEvent();
// Find out how much time that passed...
long timeDifference = event.getTime()-clock;
// ...and update the clock.
clock = event.getTime();
/* Let the GUI know that time passed. */
Consumer<Long> cb = onTimeStep;
if (cb != null) { cb.accept(timeDifference); }
// Let the cpu, memory unit, io and the GUI know that time has passed
cpu.timePassed(timeDifference);
memory.timePassed(timeDifference);
io.timePassed(timeDifference);
// Deal with the event
if (clock < simulationLength) {
processEvent(event);
}
// Let the GUI know we handled an event.
cb = onEventHandled;
if (cb != null) { cb.accept(timeDifference); }
// Note that the processing of most events should lead to new
// events being added to the event queue!
}
System.out.println("..done.");
// End the simulation by printing out the required statistics
statistics.printReport(simulationLength);
}
/**
* Processes an event by inspecting its type and delegating
* the work to the appropriate method.
* @param event The event to be processed.
*/
private void processEvent(Event event) {
switch (event.getType()) {
case Event.NEW_PROCESS:
createProcess();
break;
case Event.SWITCH_PROCESS:
switchProcess();
break;
case Event.END_PROCESS:
endProcess();
break;
case Event.IO_REQUEST:
processIoRequest();
break;
case Event.END_IO:
endIoOperation();
break;
}
}
/**
* Simulates a process arrival/creation.
*/
private void createProcess() {
// Create a new process
Process newProcess = new Process(memory.getMemorySize(), clock);
memory.insertProcess(newProcess);
transferProcessFromMemToReady();
// Add an event for the next process arrival
long nextArrivalTime = clock + 1 + (long)(2*Math.random()*avgArrivalInterval);
eventQueue.insertEvent(new Event(Event.NEW_PROCESS, nextArrivalTime));
// Update statistics
statistics.nofCreatedProcesses++;
}
/**
* Transfers processes from the memory queue to the ready queue as long as there is enough
* memory for the processes.
*/
private void transferProcessFromMemToReady() {
Process p = memory.checkMemory(clock);
// As long as there is enough memory, processes are moved from the memory queue to the cpu queue
while(p != null) {
Event event = cpu.insertProcess(p, clock);
p.leftMemoryQueue(clock);
// Also add new events to the event queue if needed
if(event != null){
eventQueue.insertEvent(event);
}
// Check for more free memory
p = memory.checkMemory(clock);
// Try to use the freed memory:
//transferProcessFromMemToReady();
}
}
/**
* Simulates a process switch.
*/
private void switchProcess() {
Event event = getCpu().switchProcess(clock);
// Updating number of times a process has been switched out by using the full time quanta
statistics.nofProcessSwitches++;
// Also add new events to the event queue if needed
if(event != null){
eventQueue.insertEvent(event);
}
}
/**
* Ends the active process, and deallocate any resources allocated to it.
*/
private void endProcess() {
/* Updating statistics and deallocating resources */
Process process = cpu.getActiveProcess();
memory.processCompleted(process);
process.updateStatistics(statistics);
/* Updating eventQueue if necessary */
Event event = cpu.activeProcessLeft(clock);
if(event != null){
eventQueue.insertEvent(event);
}
}
/**
* Processes an event signifying that the active process needs to
* perform an I/O operation.
*/
private void processIoRequest() {
/* Taking the CPU from the process and puts it in a IO queue */
Process process = cpu.getActiveProcess();
Event IoEvent = io.addIoRequest(process, clock);
/* Updating eventQueue if necessary */
if (IoEvent != null){
eventQueue.insertEvent(IoEvent);
}
/* CPU must know that the active process left */
Event event = cpu.activeProcessLeft(clock);
/* Updating eventQueue if necessary */
if (event != null){
eventQueue.insertEvent(event);
}
}
/**
* Processes an event signifying that the process currently doing I/O
* is done with its I/O operation.
*/
private void endIoOperation() {
/* Freeing I/O and puts the process in the CPU queue */
Process process = io.removeActiveProcess(clock);
Event event = cpu.insertProcess(process, clock);
/* Updating eventQueue if necessary */
if (event != null){
eventQueue.insertEvent(event);
}
/* Starting new I/O operation */
Event IoEvent = io.startIoOperation(clock);
/* Updating eventQueue if necessary */
if (IoEvent != null){
eventQueue.insertEvent(IoEvent);
}
// Updating statistics
statistics.nofProcessedIoOperations++;
}
/* The following methods are used by the GUI and should not be removed or modified. */
public LinkedList<Process> getMemoryQueue() {
return memoryQueue;
}
public LinkedList<Process> getCpuQueue() {
return cpuQueue;
}
public LinkedList<Process> getIoQueue() {
return ioQueue;
}
public Memory getMemory() {
return memory;
}
public Cpu getCpu() {
return cpu;
}
public Io getIo() {
return io;
}
public void setOnTimeStep(Consumer<Long> onTimeStep) {
this.onTimeStep = onTimeStep;
}
public void setOnEventHandled(Consumer<Long> onEventHandled) {
this.onEventHandled = onEventHandled;
}
}