2
2
* @file
3
3
* @brief Implementation of SJF CPU scheduling algorithm
4
4
* @details
5
- * shortest job first (SJF), also known as shortest job next (SJN), is a scheduling policy
6
- * that selects for execution the waiting process with the smallest execution time.
7
- * SJN is a non-preemptive algorithm. Shortest remaining time is a preemptive variant of SJN.
5
+ * shortest job first (SJF), also known as shortest job next (SJN), is a
6
+ * scheduling policy that selects for execution the waiting process with the
7
+ * smallest execution time. SJN is a non-preemptive algorithm. Shortest
8
+ * remaining time is a preemptive variant of SJN.
8
9
* @link https://www.guru99.com/shortest-job-first-sjf-scheduling.html
9
10
* @author [Lakshmi Srikumar](https://github.com/LakshmiSrikumar)
10
11
*/
11
12
12
- #include < algorithm> // / for sorting
13
- #include < cassert> // / for assert
14
- #include < random > // / random number generation
15
- #include < iomanip > // / for formatting the output
16
- #include < iostream > // / for IO operations
17
- #include < queue > // / for std::priority_queue
18
- #include < unordered_set> // / for std::unordered_set
19
- #include < vector> // / for std::vector
13
+ #include < algorithm> // / for sorting
14
+ #include < cassert> // / for assert
15
+ #include < iomanip > // / for formatting the output
16
+ #include < iostream > // / for IO operations
17
+ #include < queue > // / for std::priority_queue
18
+ #include < random > // / random number generation
19
+ #include < unordered_set> // / for std::unordered_set
20
+ #include < vector> // / for std::vector
20
21
21
22
using std::cin;
22
23
using std::cout;
@@ -59,13 +60,14 @@ bool sortcol(tuple<S, T, E>& t1, tuple<S, T, E>& t2) {
59
60
template <typename S, typename T, typename E>
60
61
class Compare {
61
62
public:
62
-
63
- /* *
63
+ /* *
64
64
* @param t1 First tuple
65
65
* @param t2 Second tuple
66
66
* @brief A comparator function that checks whether to swap the two tuples
67
67
* or not.
68
- * <a href="https://www.geeksforgeeks.org/comparator-class-in-c-with-examples/"> detailed description of comparator </a>
68
+ * <a
69
+ * href="https://www.geeksforgeeks.org/comparator-class-in-c-with-examples/">
70
+ * detailed description of comparator </a>
69
71
* @returns true if the tuples SHOULD be swapped
70
72
* @returns false if the tuples SHOULDN'T be swapped
71
73
*/
@@ -92,7 +94,7 @@ class Compare {
92
94
*/
93
95
template <typename S, typename T, typename E>
94
96
class SJF {
95
- /* *
97
+ /* *
96
98
* Priority queue of schedules(stored as tuples) of processes.
97
99
* In each tuple
98
100
* 1st element: Process ID
@@ -104,16 +106,17 @@ class SJF {
104
106
*/
105
107
priority_queue<tuple<S, T, E, double , double , double >,
106
108
vector<tuple<S, T, E, double , double , double >>,
107
- Compare<S, T, E>> schedule;
108
-
109
+ Compare<S, T, E>>
110
+ schedule;
111
+
109
112
// Stores final status of all the processes after completing the execution.
110
113
vector<tuple<S, T, E, double , double , double >> result;
111
-
114
+
112
115
// Stores process IDs. Used for confirming absence of a process while it.
113
116
unordered_set<S> idList;
114
117
115
118
public:
116
- /* *
119
+ /* *
117
120
* @brief Adds the process to the ready queue if it isn't already there
118
121
* @param id Process ID
119
122
* @param arrival Arrival time of the process
@@ -122,7 +125,7 @@ class SJF {
122
125
*
123
126
*/
124
127
void addProcess (S id, T arrival, E burst) {
125
- // Add if a process with process ID as id is not found in idList.
128
+ // Add if a process with process ID as id is not found in idList.
126
129
if (idList.find (id) == idList.end ()) {
127
130
tuple<S, T, E, double , double , double > t =
128
131
make_tuple (id, arrival, burst, 0 , 0 , 0 );
@@ -131,35 +134,39 @@ class SJF {
131
134
}
132
135
}
133
136
134
- /* *
135
- * @brief Algorithm for scheduling CPU processes according to the Shortest Job
136
- First (SJF) scheduling algorithm.
137
- *
138
- * @details Non pre-emptive SJF is an algorithm that schedules processes based on the length
139
- * of their burst times. The process with the smallest burst time is executed first.
140
- * In a non-preemptive scheduling algorithm, once a process starts executing,
141
- * it runs to completion without being interrupted.
142
- *
143
- * I used a min priority queue because it allows you to efficiently pick the process
144
- * with the smallest burst time in constant time, by maintaining a priority order where
145
- * the shortest burst process is always at the front.
146
- *
147
- * @returns void
148
- */
137
+ /* *
138
+ * @brief Algorithm for scheduling CPU processes according to the Shortest Job
139
+ First (SJF) scheduling algorithm.
140
+ *
141
+ * @details Non pre-emptive SJF is an algorithm that schedules processes based
142
+ on the length
143
+ * of their burst times. The process with the smallest burst time is executed
144
+ first.
145
+ * In a non-preemptive scheduling algorithm, once a process starts executing,
146
+ * it runs to completion without being interrupted.
147
+ *
148
+ * I used a min priority queue because it allows you to efficiently pick the
149
+ process
150
+ * with the smallest burst time in constant time, by maintaining a priority
151
+ order where
152
+ * the shortest burst process is always at the front.
153
+ *
154
+ * @returns void
155
+ */
149
156
150
157
vector<tuple<S, T, E, double , double , double >> scheduleForSJF () {
151
- // Variable to keep track of time elapsed so far
158
+ // Variable to keep track of time elapsed so far
152
159
double timeElapsed = 0 ;
153
160
154
161
while (!schedule.empty ()) {
155
162
tuple<S, T, E, double , double , double > cur = schedule.top ();
156
-
157
- // If the current process arrived at time t2, the last process
163
+
164
+ // If the current process arrived at time t2, the last process
158
165
// completed its execution at time t1, and t2 > t1.
159
166
if (get<1 >(cur) > timeElapsed) {
160
167
timeElapsed += get<1 >(cur) - timeElapsed;
161
168
}
162
-
169
+
163
170
// Add Burst time to time elapsed
164
171
timeElapsed += get<2 >(cur);
165
172
@@ -184,8 +191,8 @@ class SJF {
184
191
* @returns void
185
192
*/
186
193
187
- void printResult (const vector<tuple<S, T, E, double , double , double >>& processes) {
188
-
194
+ void printResult (
195
+ const vector<tuple<S, T, E, double , double , double >>& processes) {
189
196
cout << std::setw (17 ) << left << " Process ID" << std::setw (17 ) << left
190
197
<< " Arrival Time" << std::setw (17 ) << left << " Burst Time"
191
198
<< std::setw (17 ) << left << " Completion Time" << std::setw (17 )
@@ -194,77 +201,80 @@ class SJF {
194
201
195
202
for (const auto & process : processes) {
196
203
cout << std::setprecision (2 ) << std::fixed << std::setw (17 ) << left
197
- << get<0 >(process) << std::setw (17 ) << left
198
- << get<1 >(process) << std::setw (17 ) << left
199
- << get<2 >(process) << std::setw (17 ) << left
200
- << get<3 >(process) << std::setw (17 ) << left
201
- << get<4 >(process) << std::setw (17 ) << left
202
- << get<5 >(process) << endl;
204
+ << get<0 >(process) << std::setw (17 ) << left << get<1 >(process)
205
+ << std::setw (17 ) << left << get<2 >(process) << std::setw (17 )
206
+ << left << get<3 >(process) << std::setw (17 ) << left
207
+ << get<4 >(process) << std::setw (17 ) << left << get<5 >(process)
208
+ << endl;
203
209
}
204
210
}
205
211
};
206
212
207
- /* *
208
- * @brief Computes the final status of processes after applying non-preemptive SJF scheduling
209
- * @tparam S Data type of Process ID
210
- * @tparam T Data type of Arrival time
211
- * @tparam E Data type of Burst time
212
- * @param input A vector of tuples containing Process ID, Arrival time, and Burst time
213
- * @returns A vector of tuples containing Process ID, Arrival time, Burst time,
214
- * Completion time, Turnaround time, and Waiting time
215
- */
216
- template <typename S, typename T, typename E>
217
- vector<tuple<S, T, E, double , double , double >> get_final_status (
218
- vector<tuple<S, T, E>> input) {
219
-
220
- // Sort the processes based on Arrival time and then Burst time
221
- sort (input.begin (), input.end (), sortcol<S, T, E>);
222
-
223
- // Result vector to hold the final status of each process
224
- vector<tuple<S, T, E, double , double , double >> result (input.size ());
225
- double timeElapsed = 0 ;
226
-
227
- for (size_t i = 0 ; i < input.size (); i++) {
213
+ /* *
214
+ * @brief Computes the final status of processes after applying non-preemptive
215
+ * SJF scheduling
216
+ * @tparam S Data type of Process ID
217
+ * @tparam T Data type of Arrival time
218
+ * @tparam E Data type of Burst time
219
+ * @param input A vector of tuples containing Process ID, Arrival time, and
220
+ * Burst time
221
+ * @returns A vector of tuples containing Process ID, Arrival time, Burst time,
222
+ * Completion time, Turnaround time, and Waiting time
223
+ */
224
+ template <typename S, typename T, typename E>
225
+ vector<tuple<S, T, E, double , double , double >> get_final_status (
226
+ vector<tuple<S, T, E>> input) {
227
+ // Sort the processes based on Arrival time and then Burst time
228
+ sort (input.begin (), input.end (), sortcol<S, T, E>);
229
+
230
+ // Result vector to hold the final status of each process
231
+ vector<tuple<S, T, E, double , double , double >> result (input.size ());
232
+ double timeElapsed = 0 ;
233
+
234
+ for (size_t i = 0 ; i < input.size (); i++) {
228
235
// Extract Arrival time and Burst time
229
- T arrival = get<1 >(input[i]);
230
- E burst = get<2 >(input[i]);
236
+ T arrival = get<1 >(input[i]);
237
+ E burst = get<2 >(input[i]);
231
238
232
- // If the CPU is idle, move time to the arrival of the next process
233
- if (arrival > timeElapsed) {
234
- timeElapsed = arrival;
235
- }
239
+ // If the CPU is idle, move time to the arrival of the next process
240
+ if (arrival > timeElapsed) {
241
+ timeElapsed = arrival;
242
+ }
236
243
237
- // Update timeElapsed by adding the burst time
238
- timeElapsed += burst;
244
+ // Update timeElapsed by adding the burst time
245
+ timeElapsed += burst;
239
246
240
- // Calculate Completion time, Turnaround time, and Waiting time
241
- double completion = timeElapsed;
242
- double turnaround = completion - arrival;
243
- double waiting = turnaround - burst;
247
+ // Calculate Completion time, Turnaround time, and Waiting time
248
+ double completion = timeElapsed;
249
+ double turnaround = completion - arrival;
250
+ double waiting = turnaround - burst;
244
251
245
- // Store the results in the result vector
246
- result[i] = make_tuple (get<0 >(input[i]), arrival, burst, completion, turnaround, waiting);
247
- }
248
-
249
- return result;
250
- }
252
+ // Store the results in the result vector
253
+ result[i] = make_tuple (get<0 >(input[i]), arrival, burst, completion,
254
+ turnaround, waiting);
255
+ }
256
+
257
+ return result;
258
+ }
251
259
252
260
/* *
253
261
* @brief Self-test implementations
254
262
* @returns void
255
263
*/
256
264
static void test () {
257
265
// A vector to store the results of all processes across all test cases.
258
- vector<tuple<uint32_t , uint32_t , uint32_t , double , double , double >> finalResult;
266
+ vector<tuple<uint32_t , uint32_t , uint32_t , double , double , double >>
267
+ finalResult;
259
268
260
- for (int i{}; i < 10 ; i++) {
261
- std::random_device rd; // Seeding
269
+ for (int i{}; i < 10 ; i++) {
270
+ std::random_device rd; // Seeding
262
271
std::mt19937 eng (rd ());
263
- std::uniform_int_distribution<> distr (1 , 10 );
272
+ std::uniform_int_distribution<> distr (1 , 10 );
264
273
265
- uint32_t n = distr (eng);
274
+ uint32_t n = distr (eng);
266
275
SJF<uint32_t , uint32_t , uint32_t > readyQueue;
267
- vector<tuple<uint32_t , uint32_t , uint32_t , double , double , double >> input (n);
276
+ vector<tuple<uint32_t , uint32_t , uint32_t , double , double , double >>
277
+ input (n);
268
278
269
279
// Generate random arrival and burst times
270
280
for (uint32_t i{}; i < n; i++) {
@@ -279,21 +289,19 @@ static void test() {
279
289
280
290
// Add processes to the queue
281
291
for (uint32_t i{}; i < n; i++) {
282
- readyQueue.addProcess (get<0 >(input[i]), get<1 >(input[i]), get<2 >(input[i]));
292
+ readyQueue.addProcess (get<0 >(input[i]), get<1 >(input[i]),
293
+ get<2 >(input[i]));
283
294
}
284
295
285
- // Perform SJF scheduling
296
+ // Perform SJF schedulings
286
297
auto finalResult = readyQueue.scheduleForSJF ();
287
298
288
299
// Print processes after scheduling
289
300
cout << " \n Processes after SJF scheduling:" << endl;
290
301
readyQueue.printResult (finalResult);
291
302
}
292
303
cout << " All the tests have successfully passed!" << endl;
293
- }
294
-
295
-
296
-
304
+ }
297
305
298
306
/* *
299
307
* @brief Entry point of the program
0 commit comments