I'm doing multithreading at university and we've been asked to implement the producer consumer problem in C.
My code compiles and produces the right result. From debugging it, it seems to be waiting for the semaphores to be freed etc. I'm using Xcode 6.4, hence the need for sem_open()
instead of sem_init()
. I just have a few questions regarding my code.
- Have I done it correctly? Are there any mistakes/bugs?
- If I wanted to make
buff
larger than one, would I set the semaphorefre
to have an initial value of sizebuff
? In the producer thread, would I have to callsem_wait(fre)
buff
times before I calledsem_post(busy)
? And then a similar thing in the consumer thread?
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
void * producer(void * b);
void * consumer(void * b);
void error(char msg) {
perror(&msg);
exit(1);
}
sem_t * fre, * busy;
int size_buff = 1;
char message[] = "Hello!";
int size_msg = sizeof(message);
int main(int argc, const char * argv[]) {
//declare threads
pthread_t prod,con;
int r;
//create buffer and place it on the stack
char * buff;
buff = (char *) malloc(sizeof(char) * size_buff);
//declare semaphores and initilise them
char prod_name[] = "/Prod";
char con_name[] = "/Con";
fre = sem_open(prod_name, O_CREAT, 0777, 1);
if ((int) fre == -1)
error(errno);
busy = sem_open(con_name, O_CREAT, 0777, 0);
if ((int) fre == -1)
error(errno);
//start threads
r = pthread_create(&prod, NULL, producer, (void *) buff);
if (r) {
error(r);
}
r = pthread_create(&con, NULL, consumer, (void *) buff);
if (r) {
error(r);
}
//unlink semaphores
sem_unlink(prod_name);
sem_unlink(con_name);
pthread_exit(NULL);
return 0;
}
void * producer(void * b) {
char * buff = (char *) b;
int count = 0;
//loop through message[] and write elements to buffer
while (count < size_msg) {
sem_wait(fre);
strncat(buff,&message[count],1);
sem_post(busy);
count++;
}
return NULL;
}
void * consumer(void * b) {
char * recv;
recv = malloc(sizeof(char) * size_msg);
char * buff = (char *) b;
int count = 0;
//read from the buffer
while (count < size_msg) {
sem_wait(busy);
strncat(recv, buff, 1);
memmove(buff, buff + 1, 1); //move the elements in the buffer along one, essentailly deleting the element just read
sem_post(fre);
count++;
}
printf("%s",recv);
return NULL;
}