diff --git a/src/Process.js b/src/Process.js index 159a307..41e9f1d 100644 --- a/src/Process.js +++ b/src/Process.js @@ -16,11 +16,14 @@ class Process { } setParentQueue(queue) { - + this.queue = queue } isFinished() { - + if (this.cpuTimeNeeded <= 0 && this.blockingTimeNeeded <= 0) { + return true + } + return false; } // If no blocking time is needed by this process, decrement the amount of @@ -29,7 +32,15 @@ class Process { // by emitting the appropriate interrupt // Make sure the `stateChanged` flag is toggled appropriately executeProcess(time) { - + if (this.blockingTimeNeeded == 0) { + if (time > this.cpuTimeNeeded) { + time = this.cpuTimeNeeded; + } + this.cpuTimeNeeded -= time; + } else { + this.queue.emitInterrupt(this, SchedulerInterrupt.PROCESS_BLOCKED); + this.stateChanged = !this.stateChanged; + } } // If this process requires blocking time, decrement the amount of blocking @@ -38,16 +49,32 @@ class Process { // top running queue by emitting the appropriate interrupt // Make sure the `stateChanged` flag is toggled appropriately executeBlockingProcess(time) { - + this.blockingTimeNeeded -= time; + if (this.blockingTimeNeeded < 0) { + this.blockingTimeNeeded = 0; + } + if (this.blockingTimeNeeded === 0) { + this.queue.emitInterrupt(this, SchedulerInterrupt.PROCESS_READY); + this.stateChanged = !this.stateChanged + } + // if (time > this.blockingTimeNeeded) { + // time = this.blockingTimeNeeded; + // } + // if (this.blockingTimeNeeded > 0) { + // this.blockingTimeNeeded -= time; + // } else { + // this.queue.emitInterrupt(this, SchedulerInterrupt.PROCESS_READY); + // this.stateChanged = !this.stateChanged; + // } } // Returns this process's stateChanged property isStateChanged() { - + return this.stateChanged; } get pid() { - + return this._pid; } // Private function used for testing; DO NOT MODIFY diff --git a/src/Queue.js b/src/Queue.js index 7b45fdf..43848b2 100644 --- a/src/Queue.js +++ b/src/Queue.js @@ -19,29 +19,35 @@ class Queue { // Enqueues the given process. Return the enqueue'd process enqueue(process) { - + this.processes.push(process); + process.setParentQueue(this); + return process; } // Dequeues the next process in the queue. Return the dequeue'd process dequeue() { - + return this.processes.shift(); } // Return the least-recently added process without removing it from the list of processes peek() { - + return this.processes[0]; } isEmpty() { - + if (this.processes.length <= 0) { + return true; + } else { + return false; + } } getPriorityLevel() { - + return this.priorityLevel; } getQueueType() { - + return this.queueType; } // Manages a process's execution for the given amount of time @@ -49,26 +55,44 @@ class Queue { // 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) { - + if (currentProcess.stateChanged == true) { + this.quantumClock = 0; + return; + } else { + this.quantumClock += time; + if (this.quantumClock >= this.quantum) { + this.quantumClock = 0; + this.dequeue(); + if (!currentProcess.isFinished()) { + this.scheduler.handleInterrupt(this, currentProcess, SchedulerInterrupt.LOWER_PRIORITY); + } + } + } } // 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 doCPUWork(time) { - + const process = this.peek(); + process.executeProcess(time); + this.manageTimeSlice(process, time); } // Execute the next blocking process (assuming this is the blocking queue) // This method should call `manageTimeSlice` as well as execute the next blocking process doBlockingWork(time) { - + const process = this.peek(); + process.executeBlockingProcess(time); + this.manageTimeSlice(process, time); } // The queue's interrupt handler for notifying when a process needs to be moved to a different queue // Should handle PROCESS_BLOCKED and PROCESS_READY interrupts // The process also needs to be removed from the queue emitInterrupt(source, interrupt) { - + const sourceIndex = this.processes.indexOf(source); + this.processes.splice(sourceIndex, 1); + this.scheduler.handleInterrupt(this, source, interrupt); } } diff --git a/src/Scheduler.js b/src/Scheduler.js index 3bca870..ebfa1bc 100644 --- a/src/Scheduler.js +++ b/src/Scheduler.js @@ -24,21 +24,68 @@ class Scheduler { // 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() { - + while (this.allQueuesEmpty() === false) { + const time = Date.now() + const forTimeSlice = time - this.clock; + if (this.blockingQueue.isEmpty() === false) { + this.blockingQueue.doBlockingWork(forTimeSlice); + } else { + this.runningQueues.forEach(cpuQ =>{ + if (!cpuQ.isEmpty()) { + cpuQ.doCPUWork(forTimeSlice); + } + }) + } + this.clock = time; + } + // while (this.blockingQueue) { + // this.blockingQueue.doBlockingWork(this.clock - Date.now()); + // this.clock = Date.now(); + // } + // while (this.runningQueues) { + // for (let i = 0; i < PRIORITY_LEVELS; i++) { + // this.runningQueues[i].doCPUWork(this.clock - Date.now()); + // this.clock = Date.now(); + // } + // } } allQueuesEmpty() { - + let empty = true; + for (let i = 0; i < PRIORITY_LEVELS; i++) { + if (this.runningQueues[i].isEmpty() === false) { + empty = false; + } + } + if (this.blockingQueue.isEmpty() === false) { + empty = false; + } + return empty; } addNewProcess(process) { - + this.runningQueues[0].enqueue(process); } // 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) { - + switch(interrupt) { + case "PROCESS_BLOCKED": + this.blockingQueue.enqueue(process); + break; + case "PROCESS_READY": + this.addNewProcess(process); + break; + case "LOWER_PRIORITY": + const currentQueue = this.runningQueues.indexOf(queue); + if (this.runningQueues[currentQueue + 1] && queue.getQueueType() === 'CPU_QUEUE') { + this.runningQueues[currentQueue + 1].enqueue(process); + } else { + queue.enqueue(process); + } + break; + } } // Private function used for testing; DO NOT MODIFY