I'm trying to write a message queue implementation so my threads can exchange data. To keep things simple, the queue is only responsible for sending pointers to memory. Only one thread may send messages, and only one thread may read messages.
The struct mq_t
represents a message queue.
mq_t.messages
is a circular buffer of pointers.mq_t.send
is the index of the last sent message.mq_t.recv
is the index of the next message to be received.
I'd like to know some things:
- Thread Safety: I didn't use a mutex or lock, but I think the code is quite thread-safe. Is this true?
- In the code I use things like
while (isempty(queue));
. Is there a better way to handle such things, like suspending the thread until a memory change occurs? - Cross Platform: does my code rely on some non-cross platform code or undefined behaviour?
- Are there other things wrong with my code (except the highly generic function names)?
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#define null ((void*)0)
#define SIZE 2
typedef struct {
int send;
int recv;
void * messages[SIZE];
} mq_t;
inline int isfull(mq_t * queue) {
return (queue->send+1)%SIZE == queue->recv;
}
inline int isempty(mq_t * queue) {
return queue->send == queue->recv;
}
mq_t * create(void) {
mq_t * queue = (mq_t*)malloc(sizeof(mq_t));
queue->send = 0;
queue->recv = 0;
}
void send(mq_t * queue, void * message) {
while (isfull(queue));
int next = (queue->send+1) % SIZE;
queue->messages[next] = message;
queue->send = next;
}
void * recv(mq_t * queue) {
while (isempty(queue));
void * message = queue->messages[queue->send];
queue->recv = (queue->recv+1) % SIZE;
return message;
}
void destroy(mq_t * queue) {
while (!isempty(queue));
free(queue);
}
Test:
void * sender(void * queue) {
send(queue, "hello, ");
send(queue, "world");
send(queue, "how are you?");
printf("sent data\n");
}
void * recver(void * queue) {
sleep(1);
printf("received '%s'\n", recv(queue));
printf("received '%s'\n", recv(queue));
printf("received '%s'\n", recv(queue));
}
int main() {
mq_t * queue = create();
pthread_t s, r;
pthread_create(&s, null, sender, (void*)queue);
pthread_create(&r, null, recver, (void*)queue);
pthread_join(s, null);
pthread_join(r, null);
return 0;
}
Output:
received 'hello, ' received 'world' received 'how are you?' sent data