Skip to content

Instantly share code, notes, and snippets.

@pcewing
Created June 18, 2020 01:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pcewing/acc87f68c5352e3789aca1e3564ddc20 to your computer and use it in GitHub Desktop.
Save pcewing/acc87f68c5352e3789aca1e3564ddc20 to your computer and use it in GitHub Desktop.
Simple thread-safe queue in C
#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;
}
project('queue', 'c')
executable(
'queue_test',
[
'main.c',
'queue.c',
],
dependencies : [
dependency('threads'),
])
#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);
}
#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