Skip to content

Commit cbbfc88

Browse files
Update non_preemptive_sjf_scheduling.cpp
1 parent ccb3f07 commit cbbfc88

File tree

1 file changed

+106
-98
lines changed

1 file changed

+106
-98
lines changed

cpu_scheduling_algorithms/non_preemptive_sjf_scheduling.cpp

Lines changed: 106 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,22 @@
22
* @file
33
* @brief Implementation of SJF CPU scheduling algorithm
44
* @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.
89
* @link https://www.guru99.com/shortest-job-first-sjf-scheduling.html
910
* @author [Lakshmi Srikumar](https://github.com/LakshmiSrikumar)
1011
*/
1112

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
2021

2122
using std::cin;
2223
using std::cout;
@@ -59,13 +60,14 @@ bool sortcol(tuple<S, T, E>& t1, tuple<S, T, E>& t2) {
5960
template <typename S, typename T, typename E>
6061
class Compare {
6162
public:
62-
63-
/**
63+
/**
6464
* @param t1 First tuple
6565
* @param t2 Second tuple
6666
* @brief A comparator function that checks whether to swap the two tuples
6767
* 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>
6971
* @returns true if the tuples SHOULD be swapped
7072
* @returns false if the tuples SHOULDN'T be swapped
7173
*/
@@ -92,7 +94,7 @@ class Compare {
9294
*/
9395
template <typename S, typename T, typename E>
9496
class SJF {
95-
/**
97+
/**
9698
* Priority queue of schedules(stored as tuples) of processes.
9799
* In each tuple
98100
* 1st element: Process ID
@@ -104,16 +106,17 @@ class SJF {
104106
*/
105107
priority_queue<tuple<S, T, E, double, double, double>,
106108
vector<tuple<S, T, E, double, double, double>>,
107-
Compare<S, T, E>> schedule;
108-
109+
Compare<S, T, E>>
110+
schedule;
111+
109112
// Stores final status of all the processes after completing the execution.
110113
vector<tuple<S, T, E, double, double, double>> result;
111-
114+
112115
// Stores process IDs. Used for confirming absence of a process while it.
113116
unordered_set<S> idList;
114117

115118
public:
116-
/**
119+
/**
117120
* @brief Adds the process to the ready queue if it isn't already there
118121
* @param id Process ID
119122
* @param arrival Arrival time of the process
@@ -122,7 +125,7 @@ class SJF {
122125
*
123126
*/
124127
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.
126129
if (idList.find(id) == idList.end()) {
127130
tuple<S, T, E, double, double, double> t =
128131
make_tuple(id, arrival, burst, 0, 0, 0);
@@ -131,35 +134,39 @@ class SJF {
131134
}
132135
}
133136

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+
*/
149156

150157
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
152159
double timeElapsed = 0;
153160

154161
while (!schedule.empty()) {
155162
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
158165
// completed its execution at time t1, and t2 > t1.
159166
if (get<1>(cur) > timeElapsed) {
160167
timeElapsed += get<1>(cur) - timeElapsed;
161168
}
162-
169+
163170
// Add Burst time to time elapsed
164171
timeElapsed += get<2>(cur);
165172

@@ -184,8 +191,8 @@ class SJF {
184191
* @returns void
185192
*/
186193

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) {
189196
cout << std::setw(17) << left << "Process ID" << std::setw(17) << left
190197
<< "Arrival Time" << std::setw(17) << left << "Burst Time"
191198
<< std::setw(17) << left << "Completion Time" << std::setw(17)
@@ -194,77 +201,80 @@ class SJF {
194201

195202
for (const auto& process : processes) {
196203
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;
203209
}
204210
}
205211
};
206212

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++) {
228235
// 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]);
231238

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+
}
236243

237-
// Update timeElapsed by adding the burst time
238-
timeElapsed += burst;
244+
// Update timeElapsed by adding the burst time
245+
timeElapsed += burst;
239246

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;
244251

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+
}
251259

252260
/**
253261
* @brief Self-test implementations
254262
* @returns void
255263
*/
256264
static void test() {
257265
// 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;
259268

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
262271
std::mt19937 eng(rd());
263-
std::uniform_int_distribution<> distr(1, 10);
272+
std::uniform_int_distribution<> distr(1, 10);
264273

265-
uint32_t n = distr(eng);
274+
uint32_t n = distr(eng);
266275
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);
268278

269279
// Generate random arrival and burst times
270280
for (uint32_t i{}; i < n; i++) {
@@ -279,21 +289,19 @@ static void test() {
279289

280290
// Add processes to the queue
281291
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]));
283294
}
284295

285-
// Perform SJF scheduling
296+
// Perform SJF schedulings
286297
auto finalResult = readyQueue.scheduleForSJF();
287298

288299
// Print processes after scheduling
289300
cout << "\nProcesses after SJF scheduling:" << endl;
290301
readyQueue.printResult(finalResult);
291302
}
292303
cout << "All the tests have successfully passed!" << endl;
293-
}
294-
295-
296-
304+
}
297305

298306
/**
299307
* @brief Entry point of the program

0 commit comments

Comments
 (0)