Hone logo
Hone
Problems

Preemptive Priority Scheduling in Go

This challenge asks you to implement a preemptive priority scheduling algorithm in Go. Preemptive scheduling allows higher-priority processes to interrupt lower-priority ones that are currently running, ensuring that the most important tasks are executed promptly. This is a fundamental concept in operating systems and real-time systems.

Problem Description

You are tasked with creating a preemptive priority scheduler. The scheduler will manage a queue of processes, each with a unique ID, arrival time, burst time (the time required to complete the process), and priority (lower number indicates higher priority). The scheduler should simulate the execution of these processes, preempting lower-priority processes when a higher-priority process arrives.

What needs to be achieved:

  • Implement a data structure to represent the processes.
  • Implement a scheduling algorithm that simulates preemptive priority scheduling.
  • Track the execution timeline and determine the completion time of each process.
  • Calculate and return the average waiting time and average turnaround time for all processes.

Key Requirements:

  • Processes are added to the queue based on their arrival time.
  • The scheduler should always execute the highest-priority process that is ready to run (has arrived and not completed).
  • If a higher-priority process arrives while a lower-priority process is running, the lower-priority process should be preempted (interrupted), and the higher-priority process should start executing.
  • The preempted process should be placed back in the ready queue to resume execution later.
  • The scheduler should continue until all processes have completed.

Expected Behavior:

The scheduler should produce a timeline of process execution, showing which process is running at each time unit. It should also calculate and return the average waiting time and average turnaround time.

Edge Cases to Consider:

  • Processes arriving at the same time. The scheduler should handle this consistently (e.g., FIFO among processes with the same arrival time and priority).
  • Processes with the same priority. Again, consistent behavior is expected (e.g., FIFO).
  • Empty process queue.
  • Processes with zero burst time (instantaneous processes).
  • Arrival times that are out of order (though this is not explicitly required to handle, it's good to consider).

Examples

Example 1:

Input: processes := []Process{{ID: 1, ArrivalTime: 0, BurstTime: 8, Priority: 3}, {ID: 2, ArrivalTime: 1, BurstTime: 4, Priority: 1}, {ID: 3, ArrivalTime: 2, BurstTime: 9, Priority: 2}, {ID: 4, ArrivalTime: 3, BurstTime: 5, Priority: 0}}

Output:
Timeline:
Time 0: Process 1 running
Time 1: Process 2 running
Time 5: Process 4 running
Time 10: Process 1 running
Time 14: Process 4 running
Time 19: Process 3 running
Time 28: Process 3 completed
Average Waiting Time: 8.0
Average Turnaround Time: 16.0

Explanation: Process 4 (priority 0) preempts Process 1 (priority 3) at time 1. Process 4 completes at time 5. Process 1 resumes at time 5. Process 3 (priority 2) starts at time 14.

Example 2:

Input: processes := []Process{{ID: 1, ArrivalTime: 0, BurstTime: 5, Priority: 2}, {ID: 2, ArrivalTime: 1, BurstTime: 3, Priority: 1}, {ID: 3, ArrivalTime: 2, BurstTime: 1, Priority: 3}}

Output:
Timeline:
Time 0: Process 1 running
Time 1: Process 2 running
Time 4: Process 2 completed
Time 4: Process 1 running
Time 5: Process 1 completed
Time 5: Process 3 running
Time 6: Process 3 completed
Average Waiting Time: 2.0
Average Turnaround Time: 4.0

Explanation: Process 2 preempts Process 1. Process 3 runs after Process 2 completes.

Example 3: (Edge Case - Same Priority)

Input: processes := []Process{{ID: 1, ArrivalTime: 0, BurstTime: 4, Priority: 1}, {ID: 2, ArrivalTime: 1, BurstTime: 3, Priority: 1}}

Output:
Timeline:
Time 0: Process 1 running
Time 4: Process 1 completed
Time 4: Process 2 running
Time 7: Process 2 completed
Average Waiting Time: 2.5
Average Turnaround Time: 5.5

Explanation: Processes 1 and 2 have the same priority. They are executed in FIFO order based on arrival time.

Constraints

  • The number of processes will be between 1 and 100.
  • Arrival times will be non-negative integers.
  • Burst times will be positive integers.
  • Priorities will be non-negative integers (lower number = higher priority).
  • The total simulation time will not exceed 1000 time units.
  • The average waiting time and average turnaround time should be calculated with a precision of one decimal place.

Notes

  • You'll need to define a Process struct to represent each process.
  • Consider using a priority queue (e.g., a heap) to efficiently manage the ready queue of processes. The container/heap package in Go can be helpful.
  • Think about how to represent the timeline of process execution. Printing to the console is acceptable for this challenge.
  • Focus on correctness and clarity of your code. Efficiency is less important than a working solution.
  • The order of processes with the same priority and arrival time is not strictly defined, but your solution should be consistent.
  • Consider using a time variable to track the current simulation time.
  • The Process struct should have fields for ID, ArrivalTime, BurstTime, and Priority.
  • The function should return the AverageWaitingTime and AverageTurnaroundTime as float64.
type Process struct {
	ID           int
	ArrivalTime  int
	BurstTime    int
	Priority     int
}
Loading editor...
go