-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathqueue.c
100 lines (95 loc) · 2.23 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
/**
* Luscious Locks Lab
* CS 241 - Fall 2016
*/
#include "queue.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
/**
* Struct representing a node in a queue_t
*/
typedef struct queue_node_t {
struct queue_node_t *next;
void *data;
} queue_node_t;
/**
* Struct representing a queue
*/
struct queue_t {
queue_node_t *head, *tail;
int size;
int maxSize;
pthread_cond_t cv;
pthread_mutex_t m;
};
/**
* Given data, place it on the queue. Can be called by multiple threads.
* Blocks if the queue is full.
*/
void queue_push(queue_t *queue, void *data) {
pthread_mutex_lock(&queue -> m);
while(queue -> size == queue -> maxSize){
pthread_cond_wait(&queue -> cv, &queue -> m);
}
queue_node_t *new_node = malloc(sizeof(queue_node_t));
new_node -> data = data;
new_node -> next = NULL;
if(queue -> tail){
queue -> tail -> next = new_node;
}
queue -> tail = new_node;
if(!queue -> head){
queue -> head = new_node;
}
queue -> size++;
pthread_cond_broadcast(&queue -> cv);
pthread_mutex_unlock(&queue -> m);
}
/**
* Retrieve the data from the front of the queue. Can be called by multiple
* threads.
* Blocks if the queue is empty.
*/
void *queue_pull(queue_t *queue) {
pthread_mutex_lock(&queue -> m);
while(queue -> head == NULL){
pthread_cond_wait(&queue -> cv, &queue -> m);
}
void *val = queue -> head -> data;
queue_node_t *tmp = queue -> head;
queue -> head = queue -> head -> next;
free(tmp);
queue -> size--;
pthread_cond_broadcast(&queue -> cv);
pthread_mutex_unlock(&queue -> m);
return val;
}
/**
* Allocates heap memory for a queue_t and initializes it.
* Returns a pointer to this allocated space.
*/
queue_t *queue_create(int maxSize) {
queue_t *same = malloc(sizeof(queue_t));
same -> maxSize = maxSize == 0 ? -1 : maxSize;
same -> head = NULL;
same -> tail = NULL;
same -> size = 0;
same -> maxSize = maxSize;
pthread_cond_init(&same -> cv, NULL);
pthread_mutex_init(&same -> m, NULL);
return same;
}
/**
* Destroys the queue, freeing any remaining nodes in it.
*/
void queue_destroy(queue_t *queue) {
pthread_cond_destroy(&queue -> cv);
pthread_mutex_destroy(&queue -> m);
while (queue -> head){
queue_node_t *q = queue -> head;
queue -> head = queue -> head -> next;
free(q);
}
free(queue);
}