Skip to content

Instantly share code, notes, and snippets.

@jachermocilla
Last active January 5, 2023 17:42
Show Gist options
  • Save jachermocilla/a7ab7c3992799d2b167aa3eb22d053d1 to your computer and use it in GitHub Desktop.
Save jachermocilla/a7ab7c3992799d2b167aa3eb22d053d1 to your computer and use it in GitHub Desktop.
Producer-Consumer Problem Solutions (compile with -lpthread)
#define _GNU_SOURCE //to be able to use pthread_setname_np()
//implementation of solution to prod-con from chapter 3, dino book
//not all slots are used
//-jach
//
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#define BUFFER_SIZE 5
#define NITER 10
//Function prototypes
void *producer();
void *consumer();
//Shared by the producer and consumer thread
int buffer[BUFFER_SIZE];
int in = 0; //next free position
int out = 0; //first full position
int main(){
pthread_t prod_thread, con_thread;
srand(time(NULL));
pthread_create (&prod_thread, NULL, producer, NULL);
pthread_create (&con_thread, NULL, consumer, NULL);
pthread_setname_np(prod_thread, "ProducerThread");
pthread_setname_np(con_thread, "ConsumerThread");
pthread_join(prod_thread, NULL);
pthread_join(con_thread, NULL);
return 0;
}
void *producer(){
int next_produced;
//while (1){
for (int i=0; i< NITER; i++) {
/* produce an item in next produced */
next_produced=rand() % 100 + 1;
//Do nothing until a slot is available
while (((in + 1) % BUFFER_SIZE) == out)
;
buffer[in] = next_produced;
printf("Producer produced [%d].(Placed in index:in=%d,out=%d)\n",next_produced,in,out);
in = (in + 1) % BUFFER_SIZE;
}
}
void *consumer(){
int next_consumed;
//while(1){
for (int i=0; i< NITER; i++) {
//Do nothing if the buffer is empty
while (in == out)
;
next_consumed = buffer[out];
printf("\t\tConsumer consumed [%d].(in=%d,Consumed from index: out=%d)\n",next_consumed,in,out);
out = (out + 1) % BUFFER_SIZE;
/* consume the item in next consumed */
}
}
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
//
//solution to prod-con problem using a counter to be able to use
//all slots in the buffer. it uses condition variables.
//-jach
//
#define BUFFER_SIZE 5
#define NITER 15
//Function prototypes
void *producer();
void *consumer();
//Shared by the producer and consumer thread
int buffer[BUFFER_SIZE];
int in = 0; //next free position
int out = 0; //first full position
//Counter to hold the total number of elements
//We use this in order to fill all slots.
int counter=0;
pthread_mutex_t mutex; //for mutual exclusion
pthread_cond_t item_available; //event that an item is available
pthread_cond_t slot_available; //event that a slot is available
int main(){
pthread_t prod_thread, con_thread;
srand(time(NULL));
pthread_mutex_init(&mutex,NULL); //initialize mutex and condition variables
pthread_cond_init(&item_available, NULL);
pthread_create (&prod_thread, NULL, producer, NULL);
pthread_create (&con_thread, NULL, consumer, NULL);
pthread_join(prod_thread, NULL);
pthread_join(con_thread, NULL);
printf("Counter: %d\n",counter);
return 0;
}
void *producer(){
int next_produced;
//while (1){
for (int i=0; i< NITER; i++) {
/* produce an item in next produced */
next_produced=rand() % 100 + 1;
pthread_mutex_lock(&mutex);
while (counter==BUFFER_SIZE)
pthread_cond_wait(&slot_available, &mutex); //wait for an event that a slot is available
buffer[in] = next_produced;
printf("Producer produced [%d].(Placed in index:in=%d,out=%d)\n",next_produced,in,out);
in = (in + 1) % BUFFER_SIZE;
counter++;
pthread_cond_signal(&item_available); //signal that an item is available
pthread_mutex_unlock(&mutex);
}
}
void *consumer(){
int next_consumed;
//while(1){
for (int i=0; i< NITER; i++) {
pthread_mutex_lock(&mutex);
while (counter==0)
pthread_cond_wait(&item_available, &mutex); //wait for an event that an item is available
next_consumed = buffer[out];
printf("\t\tConsumer consumed [%d].(in=%d,Consumed from index: out=%d)\n",next_consumed,in,out);
out = (out + 1) % BUFFER_SIZE;
counter--;
pthread_cond_signal(&slot_available); //signal that a slot is available
pthread_mutex_unlock(&mutex);
}
}
//OMP implementation of solution to prod-con from chapter 3, dino book
//not all slots are used
//-jach
//
// $ gcc -o prodcon_omp.exe prodcon_omp.c -fopenmp
//
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#define BUFFER_SIZE 5
#define NITER 10
//Function prototypes
void *producer();
void *consumer();
//Shared by the producer and consumer thread
int buffer[BUFFER_SIZE];
int in = 0; //next free position
int out = 0; //first full position
int main(){
srand(time(NULL));
#pragma omp parallel sections
{
#pragma omp section
producer();
#pragma omp section
consumer();
}
return 0;
}
void *producer(){
int next_produced;
//while (1){
for (int i=0; i< NITER; i++) {
next_produced=rand() % 100 + 1;
//Do nothing until a slot is available
while (((in + 1) % BUFFER_SIZE) == out)
;
buffer[in] = next_produced;
printf("Producer produced [%d].(Placed in index:in=%d,out=%d)\n",next_produced,in,out);
in = (in + 1) % BUFFER_SIZE;
}
}
void *consumer(){
int next_consumed;
//while(1){
for (int i=0; i< NITER; i++) {
//Do nothing if the buffer is empty
while (in == out)
;
next_consumed = buffer[out];
printf("\t\tConsumer consumed [%d].(in=%d,Consumed from index: out=%d)\n",next_consumed,in,out);
out = (out + 1) % BUFFER_SIZE;
}
}
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
//
//solution to prod-con problem using a counter to be able to use
//all slots in the buffer. Suffers from race condition
//-jach
//
#define BUFFER_SIZE 5
#define NITER 1000
//Function prototypes
void *producer();
void *consumer();
//Shared by the producer and consumer thread
int buffer[BUFFER_SIZE];
int in = 0; //next free position
int out = 0; //first full position
//Counter to hold the total number of elements
//We use this in order to fill all slots.
int counter=0;
int main(){
pthread_t prod_thread, con_thread;
srand(time(NULL));
pthread_create (&prod_thread, NULL, producer, NULL);
pthread_create (&con_thread, NULL, consumer, NULL);
pthread_join(prod_thread, NULL);
pthread_join(con_thread, NULL);
printf("Counter: %d\n",counter);
return 0;
}
void *producer(){
int next_produced;
//while (1){
for (int i=0; i< NITER; i++) {
/* produce an item in next produced */
next_produced=rand() % 100 + 1;
//Do nothing when the buffer is full
while (counter==BUFFER_SIZE)
;
buffer[in] = next_produced;
//printf("Producer produced [%d].(Placed in index:in=%d,out=%d)\n",next_produced,in,out);
in = (in + 1) % BUFFER_SIZE;
counter++;
}
}
void *consumer(){
int next_consumed;
//while(1){
for (int i=0; i< NITER; i++) {
//Do nothing until an item is available
while (counter==0)
;
next_consumed = buffer[out];
//printf("\t\tConsumer consumed [%d].(in=%d,Consumed from index: out=%d)\n",next_consumed,in,out);
out = (out + 1) % BUFFER_SIZE;
counter--;
}
}
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <semaphore.h>
//
// implementation of solution to prod-con using
// semaphores.
// -jach
//
//
//The number of elements in the buffer
#define BUFFER_SIZE 5
//Number of producer threads
#define NPROD 1
//Number of consumer threads
#define NCON 1
//Number of iterations in the producer
#define PRODITER 20
//Number of iterations in the consumer
#define CONITER 20
//Function prototypes
void *producer(void *);
void *consumer(void *);
//Shared data by the producer and consumer thread
//------------------------------------------------
int buffer[BUFFER_SIZE];
int in = 0; //next free position
int out = 0; //first full position
sem_t mutex; //semaphore to lock buffer
sem_t full; //counts the number of filled slots
sem_t empty; //counts the number of empty slots
//------------------------------------------------
int main(){
//Array if thread ids for producer
pthread_t prod_thread[NPROD];
//Array of thread ids for consumer
pthread_t con_thread[NCON];
int i,j;
//Placeholder of parameters passed to the thread, the id
int *prod_id,*con_id;
//Initialize the random number generator
srand(time(NULL));
sem_init(&mutex,0,1); //we lock the buffer
sem_init(&full,0,0); //no items yet
sem_init(&empty,0,BUFFER_SIZE); //all buffers are empty
for (i=0;i<NPROD;i++){
prod_id=(int *)malloc(sizeof(int));
*prod_id=i;
pthread_create (&prod_thread[0], NULL, producer, prod_id);
}
for (j=0;j<NCON;j++){
con_id=(int *)malloc(sizeof(int));
*con_id=j;
pthread_create (&con_thread[0], NULL, consumer, con_id);
}
for (i=0;i<NPROD;i++){
pthread_join(prod_thread[i], NULL);
}
for (j=0;j<NCON;j++){
pthread_join(con_thread[j], NULL);
}
return 0;
}
void *producer(void *i){
int next_produced;
int prod_id=*((int *)i);
int full_val,empty_val;
//while (1){
for (int i=0; i< PRODITER; i++) {
/* produce an item in next produced by generating a random number*/
next_produced=rand() % 100 + 1;
sem_wait(&empty); //wait for an empty slot
sem_wait(&mutex); //wait for lock to access shared data:buffer, in
//critical section
buffer[in] = next_produced;
printf("Producer %d produced [%d].(Placed in index: in=%d,out=%d,),",
prod_id, next_produced,in,out);
in = (in + 1) % BUFFER_SIZE;
sem_post(&mutex); //release the lock on the shared data
sem_post(&full); //signal that an item is available
//get the value of the semaphores
sem_getvalue(&empty,&empty_val);
sem_getvalue(&full,&full_val);
printf("semaphores: empty=%d,full=%d\n",empty_val,full_val);
}
}
void *consumer(void *i){
int next_consumed;
int con_id=*((int *)i);
int full_val,empty_val;
//while(1){
for (int i=0; i< CONITER; i++) {
sem_wait(&full); //wait for an item to be available
sem_wait(&mutex); //wait for the lock to access shared data: buffer, out
//critical section
next_consumed = buffer[out];
//get the value of the semaphores
sem_getvalue(&empty,&empty_val);
sem_getvalue(&full,&full_val);
printf("\t\tConsumer %d consumed [%d].(in=%d,Consumed from: out=%d),",
con_id,next_consumed,in,out);
out = (out + 1) % BUFFER_SIZE;
sem_post(&mutex); //release the lock on the shared data
sem_post(&empty); //signal that a new item has been consumed
//get the value of the semaphores
sem_getvalue(&empty,&empty_val);
sem_getvalue(&full,&full_val);
printf("semaphores: empty=%d,full=%d\n",empty_val,full_val);
/* consume the item in next consumed */
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment