-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathQueue.cpp
127 lines (106 loc) · 3.72 KB
/
Queue.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/**
* @file Queue.cpp
* @brief Basic queue for scheduler implementation.
*
* Example of a scheduler implemented using a queue.
* Intended to show why a queue is a decent choice for a scheduler.
*
* @date 10/31/24
* @authors Fiya Clerget, Marcello Novak
*/
#include "Queue.h"
#include <stdio.h> // For printf
#include <stdlib.h> // For rand
#include <ctime> // For time(NULL)
// Constructor and Destructor
Queue::Queue() : head(nullptr), tail(nullptr) {}
Queue::~Queue() {
while (!isEmpty()) {
pop();
}
}
// Push method to add task at the end (tail) of the queue
void Queue::push(Task task) {
QueueNode* newNode = new QueueNode{task, nullptr, tail}; // Create new node with task data
// If the queue is not empty, link the new node as the nextTask of the tail
if (tail != nullptr) {
tail->nextTask = newNode;
}
tail = newNode; // Move tail to the new node
// If the queue was empty, set head to the new node as well
if (head == nullptr) {
head = newNode;
}
}
// Pop method to remove task from the head (front) of the queue
void Queue::pop() {
if (!isEmpty()) {
QueueNode* temp = head; // Save the current head
head = head->nextTask; // Move head to the next task
if (head != nullptr) {
head->prevTask = nullptr; // Update new head's prevTask to null
} else {
tail = nullptr; // If the queue is now empty, set tail to null
}
delete temp; // Delete the old head
} else {
printf("Queue is empty, cannot pop\n");
}
}
// Top method to access front task without popping
Task* Queue::top() {
if (!isEmpty()) {
return &(head->taskData); // Return pointer to front task
} else {
printf("Queue is empty, cannot view top\n");
return nullptr;
}
}
// Bool to check if the queue is empty
bool Queue::isEmpty() {
return head == nullptr;
}
// Function to print the queue from front to end
void Queue::printQueue() {
printf("| ");
QueueNode* current = head; // Start from the head (front of the queue)
while (current != nullptr) {
printf("[%d, %d] ", current->taskData.getRequested(), current->taskData.getServiced());
current = current->nextTask; // Move towards the end (tail) of the queue
}
printf("\n");
}
// Queue scheduler example function
void Queue::runExample() {
srand(static_cast<unsigned int>(time(NULL))); // Seed the random number generator
// Counters for tasks created and serviced
int taskCounter = 0;
int servicedCounter = 0;
int timeCounter = 0;
while (timeCounter <= 10000) { // Example runs for 1000 "time units"
// 20% chance of adding a new task each "time unit"
if (rand() % 5 == 0) {
Task newTask(rand() % 6 + 1); // req between 1 and 5 "time units"
push(newTask);
taskCounter++; // Increment task counter
}
// Print the current queue
printQueue();
// Iterate front task's serviced counter
if (!isEmpty()) {
Task* currentTask = top(); // Returns pointer to front task
// If task completed, pop, else increment serviced counter
if (currentTask->getRequested() == currentTask->getServiced()) {
pop();
servicedCounter++; // Task completed
taskCounter--; // Task removed from queue
} else {
currentTask->setServiced(currentTask->getServiced() + 1);
}
}
timeCounter++; // Increment time counter
}
// Print tasks completed and tasks left in queue
printf("Tasks completed: %d\n", servicedCounter);
printf("Tasks left in queue: %d\n", taskCounter);
}