-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfinalExam.cpp
237 lines (194 loc) · 8.05 KB
/
finalExam.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/*******************************************************************************
* File Name : finalProg8130CircQueue1.cpp
* Description : Starter Code for final programming question
* skelleton
*
* Author: PROG8130
* Date: Dec 15 2021
******************************************************************************
*/
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
DWORD WINAPI myReadThreadFunction(LPVOID lpParam); // function used by read from queue thread
unsigned int putToCircularQueue(uint32_t inputBuffer); // circular queue function to add data to queue
unsigned int getFromCircularQueue(uint32_t* ptrOutputBuffer); // circular queue function to remove data from queue
unsigned int randomRange(unsigned int minVal, unsigned int maxVal); // function to generate a random number between the two values given
uint32_t simulateDeviceRead(void); // simulated read from a device of a 32 bit unsigned number
int numberOfReadsToDo(void); // returns a random number of successive calls to simulateDeviceRead to perform
#define MAX_DATA_TO_READ 5 // mamimum number of values to read from queue
#define MIN_TIMEOUT_MS 500 // minimum time between put to queue and get from queue
#define MAX_TIMEOUT_MS 5000 // maximum time between put to queue and get from queue
#define CIRCULAR_QUEUE_SIZE 10 // size of the circular queue
// data structure used to keep track of circular queue
struct myQueueStruct {
uint32_t* ptrBuffer = 0; // pointer to start of the circular queue buffer
volatile unsigned int queueCount = 0; // number of items currently in cirucular queue (optional)
volatile uint32_t* ptrCircularHead = NULL; // location where data is added to queue
volatile uint32_t* ptrCircularTail = NULL; // loation where data is removed from queue
};
struct myQueueStruct myQueue; // create an instance of the circular queue data structure
int main()
{
HANDLE hThread; // handle to thread
uint32_t inputBufferData; // last reading from the input simulator
srand((unsigned)time(NULL)); // seed the random number generator
myQueue.ptrBuffer = (uint32_t*)calloc(CIRCULAR_QUEUE_SIZE, sizeof(uint32_t));
if (myQueue.ptrBuffer == NULL)
{
printf("Error unable to allocate memory for buffer\n");
exit(-1);
}
myQueue.ptrCircularHead = myQueue.ptrCircularTail = myQueue.ptrBuffer;
// create a thread that will consume the data we type in to demonstrate dequeing the data
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
myReadThreadFunction, // thread function name
NULL, // argument to thread function (not being used)
0, // use default creation flags
NULL); // returns the thread identifier (not being used)
printf("length of circular queue is %d\n", CIRCULAR_QUEUE_SIZE);
// get a string from the console and queue it to circular queue
while (1)
{
for (int i = numberOfReadsToDo(); i != 0; i--)
{
inputBufferData = simulateDeviceRead();
printf("QUEUE: 0x%08x\n", inputBufferData); // print out the data that is being queued
// put the data into the circular queue but check if an error (marked by queue function returning 0) occurred
if (putToCircularQueue(inputBufferData) == 0)
printf("Error queuing data\n");
}
// random delay before putting more data into queue
Sleep(randomRange(MIN_TIMEOUT_MS, MAX_TIMEOUT_MS));
}
return 0;
}
// FUNCTION : myReadThreadFunction
// DESCRIPTION :
// A seperate thread from the main program that will independently check for data in queue and print it out
// PARAMETERS :
// lpParam - arguement passed into thread (not used in this example)
//
// RETURNS :
// Will never return so no effective return value
DWORD WINAPI myReadThreadFunction(LPVOID lpParam)
{
uint32_t readBuffer; // local buffer to put the data into when reading from queue and print
unsigned int readCount = 0; // the number of characters read from queue
while (1)
{
Sleep(randomRange(MIN_TIMEOUT_MS, MAX_TIMEOUT_MS)); // wait a random amount of time
// check if data is available and if so print it out
do {
readCount = getFromCircularQueue(&readBuffer);
if (readCount != 0) // check for reads that did not get any data
printf(" UNQUEUE: 0x%08x\n", readBuffer);
} while (readCount != 0);
}
return 0; // will never reach here
}
// FUNCTION : putToCircularQueue
// DESCRIPTION :
// Put the supplied uint32_t data into a circular queue
// PARAMETERS :
// inputData - an unsigned 32 bit value to be queued
//
// RETURNS :
// Number of characters successfully queued (1 on success, 0 on failure)
unsigned int putToCircularQueue(uint32_t inputData)
{
unsigned int numberOfCharsQueued = 0; // total number of integers placed in circular queue
// add code to implement the adding to the circular queue using the data structures in myQueueStruct
// and the passed in pointer and data to be added count
uint32_t* QueueEndBuffer = myQueue.ptrBuffer + CIRCULAR_QUEUE_SIZE;
*myQueue.ptrCircularTail = inputData;
myQueue.queueCount++;
numberOfCharsQueued++;
if (myQueue.ptrCircularTail == QueueEndBuffer) {
myQueue.ptrCircularTail = myQueue.ptrBuffer;
}
else {
myQueue.ptrCircularTail++;
}
*myQueue.ptrCircularTail = '\0';
return numberOfCharsQueued;
}
// FUNCTION : getFromCircularQueue
// DESCRIPTION :
// Read as much data as there is room for from the circular queue
// PARAMETERS :
// ptrOutputBuffer - a pointer to a unsigned 32 bit number that was read from queue
//
// RETURNS :
// Number of characters successfully removed from queue (1 if successful, 0 if none are read)
unsigned int getFromCircularQueue(uint32_t* ptrOutputBuffer)
{
unsigned int readCount = 0; //set the read count to zero
// add code to implement the removing from the circular queue using the data structures in myQueueStruct
// and place the data into the ptrOutputBuffer location (note this is a uint32_t )
while (1) {
uint32_t* QueueEndBuffer = myQueue.ptrBuffer + CIRCULAR_QUEUE_SIZE;
if (myQueue.queueCount == 0) {
break;
}
*ptrOutputBuffer = *myQueue.ptrCircularHead;
myQueue.queueCount--;
readCount++;
ptrOutputBuffer++;
if (QueueEndBuffer == myQueue.ptrCircularHead) {
myQueue.ptrCircularHead = myQueue.ptrBuffer;
}
else {
myQueue.ptrCircularHead++;
}
}
*ptrOutputBuffer = '\0';
return readCount;
}
// FUNCTION : randomRange
// DESCRIPTION :
// function that returns an unsigned int random number that is between the two minVal and maxVal
// PARAMETERS :
// minVal - minimum number that can be randomly returned
// maxVal - maximum number that can be randomly returned
//
// RETURNS :
// A random number that meets the minVal/maxVal specification
unsigned int randomRange(unsigned int minVal, unsigned int maxVal)
{
unsigned int randomVal = 0;
randomVal = (unsigned int)((((double)rand() / ((uint32_t)RAND_MAX + 1)) * (maxVal - minVal)) + minVal);
return randomVal;
}
// FUNCTION : simulateDeviceRead
// DESCRIPTION :
// simulates a device returning a single unsigned 32 bit value
// PARAMETERS :
// none
//
// RETURNS :
// An unsigned 32 bit number that is meant to simulate reading the value from a device
uint32_t simulateDeviceRead(void)
{
uint32_t randomVal = 0;
randomVal = randomRange(1, 10000);
return randomVal;
}
// FUNCTION : numberOfReadsToDo
// DESCRIPTION :
// Returns a random number between 1 and 3 that represents how many reads from Device to do
// PARAMETERS :
// none
//
// RETURNS :
// A number between 1 and 3
int numberOfReadsToDo(void)
{
int retValue = 0;
retValue = randomRange(1, 3);
return retValue;
}
// * * *