lots of stuff
[assignments.git] / homework / assgn9 / queue.c
CommitLineData
165869e8 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
17static void clear_node(queue_node_t* node)
18{
19 if (node != NULL)
20 {
21 clear_node(node->next);
22 free(node);
23 }
24}
25
26static 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
36void 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
54void 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 */
64void 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 */
92int 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}