diff --git a/src/Process.js b/src/Process.js index 159a307..97c5ed5 100644 --- a/src/Process.js +++ b/src/Process.js @@ -16,11 +16,11 @@ class Process { } setParentQueue(queue) { - + this.queue = queue; } isFinished() { - + return this.cpuTimeNeeded === 0 && this.blockingTimeNeeded === 0; } // If no blocking time is needed by this process, decrement the amount of @@ -28,22 +28,37 @@ class Process { // If blocking time is needed by this process, move it to the blocking queue // by emitting the appropriate interrupt // Make sure the `stateChanged` flag is toggled appropriately - executeProcess(time) { - } + executeProcess(time) { + this.stateChanged = false; + if (this.blockingTimeNeeded === 0) { // no blocking time is needed by the process + this.cpuTimeNeeded -= time; // decrement cpu time by the input time + this.cpuTimeNeeded = this.cpuTimeNeeded > 0 ? this.cpuTimeNeeded : 0; // if blocking time is needed as stated by blockingTimeNeeded > 0 + } else { + this.queue.emitInterrupt(this, SchedulerInterrupt.PROCESS_BLOCKED); // call interrupt function and move to Blocking/Blocked queue + this.stateChanged = true; // toggle state to true + } + } // If this process requires blocking time, decrement the amount of blocking // time it needs by the input time // Once it no longer needs to perform any blocking execution, move it to the // top running queue by emitting the appropriate interrupt // Make sure the `stateChanged` flag is toggled appropriately - executeBlockingProcess(time) { + executeBlockingProcess(time) { // if process requires blocking time + this.blockingTimeNeeded -= time; // decrease blocking time by time + this.blockingTimeNeeded = this.blockingTimeNeeded > 0 ? this.blockingTimeNeeded : 0; + + if (this.blockingTimeNeeded === 0) { // if blockingTime is 0, then it's finished + this.queue.emitInterrupt(this, SchedulerInterrupt.PROCESS_READY); // call interrupt function and move it to top cpu queue + this.stateChanged = true; + } } // Returns this process's stateChanged property isStateChanged() { - + return this.stateChanged; } get pid() { diff --git a/src/Queue.js b/src/Queue.js index 7b45fdf..1d7cab8 100644 --- a/src/Queue.js +++ b/src/Queue.js @@ -4,7 +4,7 @@ const { SchedulerInterrupt } = require('./constants/index'); // blocking or non-blocking process class Queue { constructor(scheduler, quantum, priorityLevel, queueType) { - this.processes = []; + this.processes = []; //this is the storage for the queue // The queue's priority level; the lower the number, the higher the priority this.priorityLevel = priorityLevel; // The queue's parent scheduler @@ -19,38 +19,42 @@ class Queue { // Enqueues the given process. Return the enqueue'd process enqueue(process) { - + process.setParentQueue(this); // set parent queue to this + this.process.push(process); // push to array + return process } // Dequeues the next process in the queue. Return the dequeue'd process dequeue() { - + return this.process.shift(); //use array to shift to remove from front of queue } // Return the least-recently added process without removing it from the list of processes peek() { - + return this.process[0]; // looks at the front of the queue. Thsi will be the least recently push element } isEmpty() { - + return this.process.length === 0; // checks to see if length is longer than 0. If it is, itn't empty } getPriorityLevel() { - + return this.priorityLevel; // returns priorityLevel property of the object } getQueueType() { - + return this.queueType; // returns queueType property of object } // Manages a process's execution for the given amount of time // Processes that have had their states changed should not be affected // Once a process has received the alloted time, it needs to be dequeue'd and // then handled accordingly, depending on whether it has finished executing or not - manageTimeSlice(currentProcess, time) { - - } + manageTimeSlice(currentProcess, time) { + if (currentProcess.isStateChanged()) { + this.quantumClock = 0; + return; + } // Execute the next non-blocking process (assuming this is a CPU queue) // This method should call `manageTimeSlice` as well as execute the next running process diff --git a/src/Scheduler.js b/src/Scheduler.js index 3bca870..ed9bd53 100644 --- a/src/Scheduler.js +++ b/src/Scheduler.js @@ -1,5 +1,6 @@ -const Queue = require('./Queue'); -const { +const Queue = require('./Queue'); +const { + SchedulerInterrupt, QueueType, PRIORITY_LEVELS, } = require('./constants/index'); @@ -7,9 +8,9 @@ const { // A class representing the scheduler // It holds a single blocking queue for blocking processes and three running queues // for non-blocking processes -class Scheduler { - constructor() { - this.clock = Date.now(); +class Scheduler { + constructor() { + this.clock = Date.now(); // log the time that the last iteration finished this.blockingQueue = new Queue(this, 50, 0, QueueType.BLOCKING_QUEUE); this.runningQueues = []; // Initialize all the CPU running queues @@ -18,29 +19,50 @@ class Scheduler { } } - // Executes the scheduler in an infinite loop as long as there are processes in any of the queues - // Calculate the time slice for the next iteration of the scheduler by subtracting the current - // time from the clock property. Don't forget to update the clock property afterwards. // On every iteration of the scheduler, if the blocking queue is not empty, blocking work // should be done. Once the blocking work has been done, perform some CPU work in the same iteration. - run() { - } + run() { // represents the entire thing running + while (true) { // Executes the scheduler in an infinite loop as long as there are processes in any of the queues - allQueuesEmpty() { + const time = Date.now(); + // Calculate the time slice for the next iteration of the scheduler by subtracting the current + // time from the clock property. + // represents how much time from the last iteration has elapsed with the time right now/ current time + const timeSlice = time - this.clock; + // Don't forget to update the clock property afterwards. + this.clock = time; - } + if (!this.blockingQueue.isEmpty()) { // if blocking queue is not empty + this.blockingQueue.doBlockingWork(timeSlice); // call doBlocingWork with time slice/ input + } - addNewProcess(process) { + for (let i = 0; i < PRIORITY_LEVELS; i++) { + const queue = this.runningQueues[i]; // grab the running queue + if (!queue.isEmpty()) { + queue.doCPUWork(timeSlice); + break; + } + } + if (this.allQueuesEmpty()) { // checking if all queues are empty + console.log('Done!'); + break; + } + } } - // The scheduler's interrupt handler that receives a queue, a process, and an interrupt string constant - // Should handle PROCESS_BLOCKED, PROCESS_READY, and LOWER_PRIORITY interrupts. - handleInterrupt(queue, process, interrupt) { + allQueuesEmpty() { + return this.runningQueues.every((queue) => queue.isEmpty()) && this.blockingQueue.isEmpty(); // use every array method; takes in a call back on every element in the array of the running queue + } + addNewProcess(process) { + this.runningQueues[0].enqueue(process); } + + + // Private function used for testing; DO NOT MODIFY _getCPUQueue(priorityLevel) { return this.runningQueues[priorityLevel];