Implementing FCFS Scheduling Algorithm in C++

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

  1. 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.
  2. 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.
  3. Turnaround Time — Simply TT = WT + BurstTime. It represents the total elapsed time a process experiences from arrival to completion.
  4. 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

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.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.