In this post, we implement the First Come First Serve (FCFS) CPU scheduling algorithm in C++. FCFS is the simplest scheduling strategy — the process that arrives first in the ready queue gets the CPU first. It is non-preemptive: once a process starts, it runs to completion without interruption.
What is FCFS Scheduling?
FCFS works exactly like a real-world queue: the first person in line is served first. The CPU picks the first process from the ready queue, runs it completely, then picks the next. No reordering happens — processes execute strictly in arrival order.
The key metrics computed are:
- Waiting Time (WT) — Time a process spends waiting before the CPU is allocated to it. Formula:
WT[i] = WT[i-1] + BurstTime[i-1] - (ArrivalTime[i] - ArrivalTime[i-1]) - Turnaround Time (TT) — Total time from arrival to completion. Formula:
TT[i] = WT[i] + BurstTime[i]
A well-known drawback is the Convoy Effect — a long process can block many short ones behind it, inflating average waiting time.
C++ Code Implementation
// ============================================================
// First Come First Serve (FCFS) CPU Scheduling Algorithm
// Non-preemptive: processes execute in the order they arrive
// ============================================================
#include <iostream>
using namespace std;
int main() {
const int PROCESS_COUNT = 4; // Fixed number of processes
int arrivalTime[PROCESS_COUNT]; // Time at which each process arrives
int burstTime[PROCESS_COUNT]; // CPU time required by each process
int waitingTime[PROCESS_COUNT]; // Time each process waits in the ready queue
int turnaroundTime[PROCESS_COUNT];// Total time from arrival to completion
// -------------------------------------------------------
// Step 1: Read arrival and burst times from the user
// -------------------------------------------------------
for (int i = 0; i < PROCESS_COUNT; i++) {
cout << "\n Enter arrival time of P" << i + 1 << ": ";
cin >> arrivalTime[i];
cout << " Enter burst time of P" << i + 1 << ": ";
cin >> burstTime[i];
}
// -------------------------------------------------------
// Step 2: Calculate Waiting Time and Turnaround Time
// -------------------------------------------------------
// The first process has no prior process, so its waiting time is 0
waitingTime[0] = 0;
turnaroundTime[0] = burstTime[0]; // TT[0] = 0 + BurstTime[0]
int totalBurstTime = burstTime[0];
for (int i = 1; i < PROCESS_COUNT; i++) {
// WT[i] = WT[i-1] + Burst[i-1] - (Arrival[i] - Arrival[i-1])
// The subtraction accounts for any idle gap between arrivals
waitingTime[i] = waitingTime[i-1] + burstTime[i-1]
- (arrivalTime[i] - arrivalTime[i-1]);
// Waiting time cannot be negative (process arrived after CPU was free)
if (waitingTime[i] < 0) waitingTime[i] = 0;
turnaroundTime[i] = waitingTime[i] + burstTime[i]; // TT = WT + BT
totalBurstTime += burstTime[i];
}
// -------------------------------------------------------
// Step 3: Display the scheduling result table
// -------------------------------------------------------
cout << "\n Result";
cout << "\n===BEFORE===PNO\tAT\tWT\tBT\tTT";
for (int i = 0; i < PROCESS_COUNT; i++) {
cout << "\n P" << i + 1
<< "\t" << arrivalTime[i]
<< "\t" << waitingTime[i]
<< "\t" << burstTime[i]
<< "\t" << turnaroundTime[i];
}
cout << "\n Total Burst Time: " << totalBurstTime;
// -------------------------------------------------------
// Step 4: Compute and display averages
// -------------------------------------------------------
int totalWaitingTime = 0, totalTurnaroundTime = 0;
for (int i = 0; i < PROCESS_COUNT; i++) {
totalWaitingTime += waitingTime[i];
totalTurnaroundTime += turnaroundTime[i];
}
float avgWaitingTime = (float)totalWaitingTime / PROCESS_COUNT;
float avgTurnaroundTime = (float)totalTurnaroundTime / PROCESS_COUNT;
cout << "\n Average Waiting Time : " << avgWaitingTime;
cout << "\n Average Turnaround Time : " << avgTurnaroundTime;
cout << endl;
return 0;
}
Explanation of the Code
- Input — Reads arrival time and burst time for each of the 4 processes sequentially. FCFS assumes processes arrive and are queued in this input order.
- Waiting Time — The first process always waits 0. For each subsequent process, the formula
WT[i] = WT[i-1] + BT[i-1] - (AT[i] - AT[i-1])calculates how long the process waits. The(AT[i] - AT[i-1])term subtracts any gap during which the CPU was idle between arrivals. A negative-guard prevents impossible values. - Turnaround Time — Simply
TT = WT + BurstTime. It represents the total elapsed time a process experiences from arrival to completion. - Averages — Totals are accumulated then divided by process count to yield average WT and TT, which are the primary performance metrics for comparing scheduling algorithms.
Sample Output
Enter arrival time of P1: 0
Enter burst time of P1: 2
Enter arrival time of P2: 1
Enter burst time of P2: 6
Enter arrival time of P3: 2
Enter burst time of P3: 9
Enter arrival time of P4: 3
Enter burst time of P4: 1
Result
PNO AT WT BT TT
P1 0 0 2 2
P2 1 1 6 7
P3 2 6 9 15
P4 3 14 1 15
Total Burst Time: 18
Average Waiting Time : 5.25
Average Turnaround Time : 9.75
Step-by-Step Explanation of Input/Output
Input used: P1(AT=0,BT=2), P2(AT=1,BT=6), P3(AT=2,BT=9), P4(AT=3,BT=1)
Gantt Chart:
| P1 (0–2) | P2 (2–8) | P3 (8–17) | P4 (17–18) |
- P1: Arrives at 0, starts immediately. WT = 0. TT = 0 + 2 = 2. CPU free at time 2.
- P2: Arrives at 1, CPU free at 2. Waits 2 − 1 = 1. WT = 1. TT = 1 + 6 = 7. CPU free at time 8.
- P3: Arrives at 2, CPU free at 8. Waits 8 − 2 = 6. WT = 6. TT = 6 + 9 = 15. CPU free at time 17.
- P4: Arrives at 3, CPU free at 17. Waits 17 − 3 = 14. WT = 14. TT = 14 + 1 = 15.
- Average WT = (0 + 1 + 6 + 14) / 4 = 21 / 4 = 5.25
- Average TT = (2 + 7 + 15 + 15) / 4 = 39 / 4 = 9.75
Notice how P4 (burst time = 1) waits 14 units because the long P3 runs ahead of it — this is the Convoy Effect in action.
See Also
- Implementing SJF (Shortest Job First) Scheduling Algorithm in C++
- Implementing Round Robin Scheduling Algorithm in C++
- Implementation of Priority Scheduling Algorithm in C++
Bottom line is…
FCFS is the easiest scheduling algorithm to understand and implement, but it is rarely used in practice because of the Convoy Effect. It performs well only when all processes have roughly equal burst times or when fairness based on arrival order is the top priority. More intelligent algorithms like SJF and Round Robin were developed specifically to overcome FCFS’s weaknesses.