-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathqueue.c
More file actions
136 lines (106 loc) · 2.65 KB
/
queue.c
File metadata and controls
136 lines (106 loc) · 2.65 KB
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
/*
* queue.c
*
* Created on: Apr 3, 2017
* Author: spm5065
*/
#include <time.h>
#include "queue.h"
Customer *queue[QUEUE_SIZE];
int numInQueue;
pthread_mutex_t queueLock;
sem_t turnSemaphore;
int tNextCust = 0;
//Initialize the queue
void initQueue() {
memset( queue, 0, sizeof(Customer *) * QUEUE_SIZE );
if (pthread_mutex_init( &queueLock, NULL)) {
puts("Failed to initialize the mutex.");
}
if ( sem_init(&turnSemaphore, 0, 3360) ){
puts("Failed to initialize the semaphore.");
}
tNextCust = RandomNextCustomerTime();
}
//Cleanup queue
void destroyQueue(){
for(int i = 0; i < QUEUE_SIZE; i++){
if( queue[i] ) free(queue[i]);
queue[i] = NULL;
}
pthread_mutex_destroy( &queueLock );
sem_destroy(&turnSemaphore);
}
void UpdateQueueMetrics(){
//Ensure we store the max number of people in the queue
if(numInQueue > Bank.maxNumInQueue){
Bank.maxNumInQueue = numInQueue;
}
//Increment each persons time in the queue
for(int i = 0; i < numInQueue; i++){
queue[i]->timeInQueue++;
}
}
int doQueueAction(){
int turn = -1; //Value for turn
int rc = 1; //Return Code
//Get the turn, and check if its my turn
if( (sem_getvalue( &turnSemaphore, &turn ) != -1) && (turn % 4 == 0) ){
//Are we open
if(turn > 0){
if (--tNextCust <= 0) {
Customer *newCust = (Customer *) malloc(sizeof(Customer));
pushQueue(newCust);
tNextCust = RandomNextCustomerTime();
}
} else { //Not open
if(numInQueue == 0) rc = 0;
}
UpdateQueueMetrics();
struct timespec t;
t.tv_sec = 0;
t.tv_nsec = 50000000;
nanosleep(&t, NULL);
if (turn != 0) sem_wait(&turnSemaphore);
}
struct timespec t;
t.tv_sec = 0;
t.tv_nsec = 5000;
nanosleep(&t, NULL);
return rc;
}
void runQueue(){
int i = 0;
while (doQueueAction() && i < 100000){i++;}//doAction endlessly
}
//Thread-safe queue grab
int getQueueSize(){
pthread_mutex_lock(&queueLock);
int value = numInQueue;
pthread_mutex_unlock(&queueLock);
return value;
}
//Add customer to the queue
void pushQueue(Customer *cust){
pthread_mutex_lock(&queueLock);
queue[numInQueue++] = cust;
if(Bank.maxNumInQueue < numInQueue) Bank.maxNumInQueue = numInQueue;
pthread_mutex_unlock(&queueLock);
}
//Get a customer from the queue
Customer *popQueue(){
//Get a lock on the mutex
pthread_mutex_lock(&queueLock);
Customer *returnCust = NULL;
if( numInQueue > 0) {
//Get customer and dec num in queue
returnCust = queue[0];
numInQueue--;
//shift people forward in queue and remove dupe
memcpy(&queue[0], &queue[1], sizeof(Customer *) * (QUEUE_SIZE - 1) );
queue[QUEUE_SIZE - 1] = 0;
}
//Unlock the mutex
pthread_mutex_unlock(&queueLock);
return returnCust;
}