#include "queue.h" #include #include /* Requirements 4 & 5 for Homework 09 indicate that you should modify the add * and pop methods for the queue to provide for thread safety. If you modify * the producer and consumer methods instead you will not receive full credit * for the solution. Additionally, the due date for the homework is now * Thursday to provide for the necessary modifications to fulfill requirements * 4 & 5. Please note that you should NOT be using a global mutex. Any * structures you use to protect the queue should be associated with the * particular queue that is being used (the one given to the add/pop methods). * */ /* private methods */ static void clear_node(queue_node_t* node) { if (node != NULL) { clear_node(node->next); free(node); } } static queue_node_t* create_node(int value) { queue_node_t* node = malloc(sizeof(queue_node_t)); node->value = value; node->next = NULL; return node; } /* public methods */ void queue_init(queue_t* queue) { queue->root = NULL; queue->mx_pop = (pthread_mutex_t *) calloc(1, sizeof(pthread_mutex_t)); queue->mx_push = (pthread_mutex_t *) calloc(1, sizeof(pthread_mutex_t)); queue->mx_valid_root = (pthread_mutex_t *) calloc(1, sizeof(pthread_mutex_t)); queue->valid_root = (pthread_cond_t *) calloc(1, sizeof(pthread_cond_t)); pthread_mutex_init(queue->mx_pop, NULL); pthread_mutex_init(queue->mx_push, NULL); pthread_mutex_init(queue->mx_valid_root, NULL); pthread_cond_init(queue->valid_root, NULL); return; } void queue_clear(queue_t* queue) { clear_node(queue->root); free(queue->mx_pop); free(queue->mx_push); free(queue->valid_root); return; } /* edit */ void queue_add(queue_t* queue, int value) { pthread_mutex_lock(queue->mx_push); pthread_mutex_lock(queue->mx_valid_root); if (queue->root == NULL) { queue->root = create_node(value); pthread_cond_signal(queue->valid_root); pthread_mutex_unlock(queue->mx_valid_root); } else { pthread_cond_signal(queue->valid_root); pthread_mutex_unlock(queue->mx_valid_root); queue_node_t* last = queue->root; while (last->next != NULL) { last = last->next; } last->next = create_node(value); } pthread_mutex_unlock(queue->mx_push); return; } /* edit */ int queue_pop(queue_t* queue) { if(queue->root == NULL) { pthread_mutex_lock(queue->mx_valid_root); pthread_cond_wait(queue->valid_root, queue->mx_valid_root); pthread_mutex_unlock(queue->mx_valid_root); } pthread_mutex_lock(queue->mx_pop); queue_node_t* temp = queue->root->next; int value = queue->root->value; free(queue->root); queue->root = temp; pthread_mutex_unlock(queue->mx_pop); return value; }