-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathQueue.c
166 lines (154 loc) · 4.77 KB
/
Queue.c
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
////////////////////////////////////////////////////////////////////////////////
// Main File: main.c
// This File: Queue.c
// Other Files: inputreader.c inputreader.h munch1.c munch1.h munch2.c
// munch2.h outputwriter.c outputwriter.h Queue.h
// Semester: CS 537 Fall 2018
//
// Author: Youmin Han
// Email: [email protected]
// CS Login: youmin
//
// Author: Xianjie Zheng
// Email: [email protected]
// CS Login: xianjie
//
/////////////////////////// OTHER SOURCES OF HELP //////////////////////////////
// fully acknowledge and credit all sources of help,
// other than Instructors and TAs.
//
// Persons: NULL
//
// Online sources: NULL
//
//////////////////////////// 80 columns wide ///////////////////////////////////
#include "Queue.h"
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>
int ModIncr(int v) {
return (v+1) % 10; //TODO
}
/*
* Dynamically allocate a new Queue structure and initialize it with an array of
* character points of length size.
* The function returns a pointer to the new queue structure.
*
* @param size : size of the queue
*/
Queue *CreateStringQueue(int size){
// edge case when size is negative
if (size <= 0) {
fprintf(stderr, "Wrong size!" );
exit(-1);
}
// create a queue struct
struct Queue *q = (Queue *)calloc(1, sizeof(Queue));
if(!q) {
fprintf(stderr, "Error allocating memory\n");
exit(1);
}
// allocate memory to the queue
q->array = malloc(size*sizeof(char*));
if(!q->array) {
fprintf(stderr, "Error allocating memory\n");
exit(1);
}
q->qsize = size;
q->enqcount = 0;
q->deqcount = 0;
q->enqblcount = 0;
q->deqblcount = 0;
q->front = 0;
q->end = 0;
pthread_cond_init(&(q->full),NULL);
pthread_cond_init(&(q->empty),NULL);
pthread_mutex_init(&(q->mutex), NULL);
return q;
}
/*
* This function places the pointer to the string at the end of queue q.
* If the queue is full, then this function blocks until there is space
* available.
* @param q : A queue that stores strings
* string : a ptr stores a string
*/
void EnqueueString(Queue *q, char *string) {
// use mutex to realize mutual exclusion
if(pthread_mutex_lock(&(q->mutex)))
fprintf(stderr, "error locking mutex");
// when the queue is full, block
while (ModIncr(q->end) == q->front){
q->enqblcount++;
if(pthread_cond_wait(&(q->full), &(q->mutex)))
fprintf(stderr, "error waiting condition variable");
}
// add string
*(q->array + q->end) = string;
if (string != NULL) {
q->enqcount++;
}
q->end = ModIncr(q->end);
// signal that there's at least one string in queue
if(pthread_cond_signal(&(q->empty)))
fprintf(stderr, "error signaling condition variable");
if(pthread_mutex_unlock(&(q->mutex)))
fprintf(stderr, "error locking mutex");
}
/*
* This function removes a pointer to a string from the beginning of queue q.
* If the queue is empty, then this function blocks until there is a string
* placed into the queue.
* Returns the pointer that was removed from the queue.
*
* @param q
* A queue that stores strings
*/
char * DequeueString(Queue *q) {
// use mutex to realize mutual exclusion
if(pthread_mutex_lock(&(q->mutex)))
fprintf(stderr, "error locking mutex");
// when the queue is empty, block
while(q->front == q->end) {
q->deqblcount++;
if(pthread_cond_wait(&(q->empty), &(q->mutex)))
fprintf(stderr, "error waiting condition variable");
}
// remove string
char *result = *(q->array + q->front);
q->front = ModIncr(q->front);
if(result != NULL) {
q->deqcount++;
}
// signal that string can be added to the queue
if(pthread_cond_signal(&(q->full)))
fprintf(stderr, "error signaling condition variable");
if(pthread_mutex_unlock(&(q->mutex)))
fprintf(stderr, "error unlocking mutex");
return result;
}
/*
* This function prints the statistics for this queue.
*
* @param q
* A queue that stores strings
*/
void PrintQueueStats(Queue *q) {
fprintf(stderr, "Number of strings enqueued: %d\n", q->enqcount);
fprintf(stderr, "Number of strings dequeued: %d\n", q->deqcount);
fprintf(stderr, "Number of times that an enqueue was blocked: %d\n", q->enqblcount);
fprintf(stderr, "Number of times that a dequeue was blocked: %d\n", q->deqblcount);
}
/*
* This function frees all the memory that a que has allocated
*
* @param q
* A queue that stores strings
*/
void DestoryQueue(Queue *q) {
free(q->array);
q->array = NULL;
free(q);
q = NULL;
}