Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "queue.h"
- #include <pthread.h>
- #include <semaphore.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- #include <assert.h>
- #define handle_error_en(en, msg) \
- do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
- #define handle_error(msg) \
- do { perror(msg); exit(EXIT_FAILURE); } while (0)
- /*
- * Queue - the abstract type of a concurrent queue.
- * You must provide an implementation of this type
- * but it is hidden from the outside.
- */
- typedef struct QueueStruct {
- void** elements; // Array of pointers to objects in queue
- int size;
- // Implement queue as a ring buffer:
- int index_last;
- int index_first;
- // Guard the queue internals from simultaneous modification
- pthread_mutex_t put_guard;
- pthread_mutex_t get_guard;
- // Also guard the queue with semaphores so it can
- // never be overfilled past its size or over-emptied
- sem_t free_slots;
- sem_t used_slots;
- } Queue;
- /**
- * Allocate a concurrent queue of a specific size
- * @param size - The size of memory to allocate to the queue
- * @return queue - Pointer to the allocated queue
- */
- Queue *queue_alloc(int size) {
- Queue* queue = malloc(sizeof(Queue));
- void** elements = malloc(size * sizeof(void*));
- queue->elements = elements;
- queue->size = size;
- queue->index_first = 0;
- queue->index_last = 0;
- pthread_mutex_init(&queue->put_guard, NULL);
- pthread_mutex_init(&queue->get_guard, NULL);
- sem_init(&queue->free_slots, 0, size);
- sem_init(&queue->used_slots, 0, 0);
- return queue;
- }
- /**
- * Free a concurrent queue and associated memory
- *
- * Don't call this function while the queue is still in use.
- * (Note, this is a pre-condition to the function and does not need
- * to be checked)
- *
- * @param queue - Pointer to the queue to free
- */
- void queue_free(Queue *queue) {
- // assert(0 && "not implemented yet!");
- }
- /**
- * Place an item into the concurrent queue.
- * If no space available then queue will block
- * until a space is available when it will
- * put the item into the queue and immediatly return
- *
- * @param queue - Pointer to the queue to add an item to
- * @param item - An item to add to queue. Uses void* to hold an arbitrary
- * type. User's responsibility to manage memory and ensure
- * it is correctly typed.
- */
- void queue_put(Queue *queue, void *item) {
- sem_wait(&queue->free_slots);
- pthread_mutex_lock(&queue->put_guard);
- queue->elements[queue->index_last] = item;
- // Increment last index modulo the queue size
- queue->index_last = (queue->index_last + 1) % queue->size;
- pthread_mutex_unlock(&queue->put_guard);
- sem_post(&queue->used_slots);
- }
- /**
- * Get an item from the concurrent queue
- *
- * If there is no item available then queue_get
- * will block until an item becomes avaible when
- * it will immediately return that item.
- *
- * @param queue - Pointer to queue to get item from
- * @return item - item retrieved from queue. void* type since it can be
- * arbitrary
- */
- void *queue_get(Queue *queue) {
- sem_wait(&queue->used_slots);
- pthread_mutex_lock(&queue->get_guard);
- void* item = queue->elements[queue->index_first];
- // Increment first index modulo queue size
- queue->index_first = (queue->index_first + 1) % queue->size;
- pthread_mutex_unlock(&queue->get_guard);
- sem_post(&queue->free_slots);
- return item;
- }
- void queue_print(Queue* queue) {
- printf("Queue: First = %d, Last = %d\n", queue->index_first, queue->index_last);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement