lots of stuff
[assignments.git] / homework / assgn9 / queue.c
1 #include "queue.h"
2 #include <stdlib.h>
3 #include <pthread.h>
4
5 /* Requirements 4 & 5 for Homework 09 indicate that you should modify the add
6 * and pop methods for the queue to provide for thread safety. If you modify
7 * the producer and consumer methods instead you will not receive full credit
8 * for the solution. Additionally, the due date for the homework is now
9 * Thursday to provide for the necessary modifications to fulfill requirements
10 * 4 & 5. Please note that you should NOT be using a global mutex. Any
11 * structures you use to protect the queue should be associated with the
12 * particular queue that is being used (the one given to the add/pop methods).
13 * */
14
15 /* private methods */
16
17 static void clear_node(queue_node_t* node)
18 {
19 if (node != NULL)
20 {
21 clear_node(node->next);
22 free(node);
23 }
24 }
25
26 static queue_node_t* create_node(int value)
27 {
28 queue_node_t* node = malloc(sizeof(queue_node_t));
29 node->value = value;
30 node->next = NULL;
31 return node;
32 }
33
34 /* public methods */
35
36 void queue_init(queue_t* queue)
37 {
38 queue->root = NULL;
39
40 queue->mx_pop = (pthread_mutex_t *) calloc(1, sizeof(pthread_mutex_t));
41 queue->mx_push = (pthread_mutex_t *) calloc(1, sizeof(pthread_mutex_t));
42 queue->mx_valid_root = (pthread_mutex_t *) calloc(1, sizeof(pthread_mutex_t));
43 queue->valid_root = (pthread_cond_t *) calloc(1, sizeof(pthread_cond_t));
44
45 pthread_mutex_init(queue->mx_pop, NULL);
46 pthread_mutex_init(queue->mx_push, NULL);
47 pthread_mutex_init(queue->mx_valid_root, NULL);
48
49 pthread_cond_init(queue->valid_root, NULL);
50
51 return;
52 }
53
54 void queue_clear(queue_t* queue)
55 {
56 clear_node(queue->root);
57 free(queue->mx_pop);
58 free(queue->mx_push);
59 free(queue->valid_root);
60 return;
61 }
62
63 /* edit */
64 void queue_add(queue_t* queue, int value)
65 {
66 pthread_mutex_lock(queue->mx_push);
67 pthread_mutex_lock(queue->mx_valid_root);
68
69 if (queue->root == NULL)
70 {
71 queue->root = create_node(value);
72 pthread_cond_signal(queue->valid_root);
73 pthread_mutex_unlock(queue->mx_valid_root);
74 }
75 else
76 {
77 pthread_cond_signal(queue->valid_root);
78 pthread_mutex_unlock(queue->mx_valid_root);
79
80 queue_node_t* last = queue->root;
81 while (last->next != NULL)
82 {
83 last = last->next;
84 }
85 last->next = create_node(value);
86 }
87 pthread_mutex_unlock(queue->mx_push);
88 return;
89 }
90
91 /* edit */
92 int queue_pop(queue_t* queue)
93 {
94 if(queue->root == NULL) {
95
96 pthread_mutex_lock(queue->mx_valid_root);
97 pthread_cond_wait(queue->valid_root, queue->mx_valid_root);
98 pthread_mutex_unlock(queue->mx_valid_root);
99 }
100 pthread_mutex_lock(queue->mx_pop);
101 queue_node_t* temp = queue->root->next;
102 int value = queue->root->value;
103 free(queue->root);
104 queue->root = temp;
105 pthread_mutex_unlock(queue->mx_pop);
106 return value;
107 }