Created
June 18, 2020 01:19
-
-
Save pcewing/acc87f68c5352e3789aca1e3564ddc20 to your computer and use it in GitHub Desktop.
Simple thread-safe queue in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "queue.h" | |
#include <stdio.h> | |
#define UNUSED(x) ((void)(x)) | |
void string_print_callback(void *item) { | |
const char *str = item; | |
printf("%s", str); | |
} | |
void int_print_callback(void *item) { | |
int *i = item; | |
printf("%i", *i); | |
} | |
int main(int argc, char *argv[]) { | |
UNUSED(argc); | |
UNUSED(argv); | |
int a = 1; | |
int b = 2; | |
int c = 3; | |
struct queue_t *queue = queue_new(sizeof(int)); | |
queue_enqueue(queue, &a); | |
queue_enqueue(queue, &b); | |
queue_enqueue(queue, &c); | |
queue_print(queue, int_print_callback); | |
int d; | |
for (int i = 0; i < 4; ++i) { | |
if (queue_dequeue(queue, &d)) | |
printf("Dequeued: %i\n", d); | |
else | |
printf("Nothing to dequeue\n"); | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
project('queue', 'c') | |
executable( | |
'queue_test', | |
[ | |
'main.c', | |
'queue.c', | |
], | |
dependencies : [ | |
dependency('threads'), | |
]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "queue.h" | |
#include <pthread.h> | |
#include <stdio.h> | |
#include <stddef.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <string.h> | |
struct queue_node_t { | |
void *data; | |
struct queue_node_t *next; | |
}; | |
struct queue_t { | |
struct queue_node_t *head; | |
struct queue_node_t *tail; | |
size_t item_size; | |
size_t size; | |
pthread_mutex_t lock; | |
}; | |
struct queue_node_t *queue_node_new(size_t item_size, void *item) { | |
struct queue_node_t *queue_node = malloc(sizeof(struct queue_node_t)); | |
if (!queue_node) | |
return NULL; | |
memset(queue_node, 0, sizeof(struct queue_node_t)); | |
queue_node->data = malloc(item_size); | |
if (!queue_node->data) { | |
free(queue_node); | |
return NULL; | |
} | |
memcpy(queue_node->data, item, item_size); | |
return queue_node; | |
} | |
void queue_node_free(struct queue_node_t *queue_node) { | |
free(queue_node); | |
} | |
struct queue_t *queue_new(size_t item_size) { | |
struct queue_t *queue = malloc(sizeof(struct queue_t)); | |
memset(queue, 0, sizeof(struct queue_t)); | |
if (queue) { | |
queue->item_size = item_size; | |
pthread_mutex_init(&queue->lock, NULL); | |
} | |
return queue; | |
} | |
void queue_free(struct queue_t *queue) { | |
pthread_mutex_destroy(&queue->lock); | |
free(queue); | |
} | |
bool queue_enqueue(struct queue_t *queue, void *item) { | |
bool result = true; | |
pthread_mutex_lock(&queue->lock); | |
struct queue_node_t *new_node = queue_node_new(queue->item_size, item); | |
if (new_node) { | |
if (queue->size == 0) | |
queue->head = queue->tail = new_node; | |
else | |
queue->tail = queue->tail->next = new_node; | |
++queue->size; | |
} else { | |
result = false; | |
} | |
pthread_mutex_unlock(&queue->lock); | |
return result; | |
} | |
bool queue_dequeue(struct queue_t *queue, void *item) { | |
bool result = true; | |
pthread_mutex_lock(&queue->lock); | |
if (queue->size == 0) { | |
result = false; | |
} else { | |
memcpy(item, queue->head->data, queue->item_size); | |
struct queue_node_t *temp = queue->head; | |
queue->head = queue->head->next; | |
queue_node_free(temp); | |
--queue->size; | |
} | |
pthread_mutex_unlock(&queue->lock); | |
return result; | |
} | |
void queue_print(struct queue_t *queue, print_callback p) { | |
pthread_mutex_lock(&queue->lock); | |
printf("[ "); | |
struct queue_node_t *itr = queue->head; | |
while (itr) { | |
p(itr->data); | |
if (itr->next) | |
printf(", "); | |
itr = itr->next; | |
} | |
printf(" ]\n"); | |
pthread_mutex_unlock(&queue->lock); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <stdbool.h> | |
#include <stddef.h> | |
struct queue_t; | |
struct queue_t *queue_new(size_t item_size); | |
void queue_free(struct queue_t *queue); | |
bool queue_enqueue(struct queue_t *queue, void *item); | |
bool queue_dequeue(struct queue_t *queue, void *item); | |
// For debugging purposes | |
typedef void(*print_callback)(void *item); | |
void queue_print(struct queue_t *queue, print_callback p); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment