#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#define BUFFER_SIZE 99
#define PRODUCTION_COST 0
char producer_array[BUFFER_SIZE * 10];
char consumer_array[BUFFER_SIZE];
int producer_index = 0;
int consumer_index = 0;
pthread_mutex_t producer_mutex;
pthread_mutex_t consumer_mutex;
void* producer1(void* arg);
void* producer2(void* arg);
void* producer3(void* arg);
void* consumer(void* arg);
int main()
{
srand(time(NULL)); // Seed the random number generator
pthread_mutex_init(&producer_mutex, NULL);
pthread_mutex_init(&consumer_mutex, NULL);
pthread_t producer_threads[3];
pthread_t consumer_threads[3];
pthread_create(&producer_threads[0], NULL, producer1, NULL);
pthread_create(&producer_threads[1], NULL, producer2, NULL);
pthread_create(&producer_threads[2], NULL, producer3, NULL);
pthread_create(&consumer_threads[0], NULL, consumer, NULL);
pthread_create(&consumer_threads[1], NULL, consumer, NULL);
pthread_create(&consumer_threads[2], NULL, consumer, NULL);
for (int i = 0; i < 3; i++) {
pthread_join(producer_threads[i], NULL);
pthread_join(consumer_threads[i], NULL);
}
printf("Consumer Array: ");
for (int i = 0; i < consumer_index; i++)
{
printf("%c", consumer_array[i]);
}
printf("\n\n");
printf("Producer Array: ");
for (int i = 0; i < producer_index; i++)
{
printf("%c", producer_array[i]);
}
printf("\n");
pthread_mutex_destroy(&producer_mutex);
pthread_mutex_destroy(&consumer_mutex);
return 0;
}
void* producer1(void* arg)
{
while (consumer_index < BUFFER_SIZE)
{
char product;
int rand_int = rand() % 2;
if (rand_int == 0)
{
product = 'B';
usleep(PRODUCTION_COST);
}
else
{
product = 'G';
usleep(PRODUCTION_COST);
}
pthread_mutex_lock(&producer_mutex);
char last_char = (producer_index > 0) ? producer_array[producer_index - 1] : '\0';
if (product == 'B')
{
if (last_char == 'R' || last_char == '\0')
{
producer_array[producer_index++] = 'B';
}
}
else if (product == 'G')
{
if (last_char == 'B')
{
producer_array[producer_index++] = 'G';
}
}
pthread_mutex_unlock(&producer_mutex);
}
return NULL;
}
void* producer2(void* arg)
{
while (consumer_index < BUFFER_SIZE)
{
char product;
int rand_int = rand() % 2;
if (rand_int == 0)
{
product = 'G';
usleep(PRODUCTION_COST);
}
else
{
product = 'R';
usleep(PRODUCTION_COST);
}
pthread_mutex_lock(&producer_mutex);
char last_char = (producer_index > 0) ? producer_array[producer_index - 1] : '\0';
if (product == 'G')
{
if (last_char == 'B')
{
producer_array[producer_index++] = 'G';
}
}
else if (product == 'R')
{
if (last_char == 'G')
{
producer_array[producer_index++] = 'R';
}
}
pthread_mutex_unlock(&producer_mutex);
}
return NULL;
}
void* producer3(void* arg)
{
while (consumer_index < BUFFER_SIZE)
{
char product;
int rand_int = rand() % 2;
if (rand_int == 0)
{
product = 'R';
usleep(PRODUCTION_COST);
}
else
{
product = 'B';
usleep(PRODUCTION_COST);
}
pthread_mutex_lock(&producer_mutex);
char last_char = (producer_index > 0) ? producer_array[producer_index - 1] : '\0';
if (product == 'R')
{
if (last_char == 'G')
{
producer_array[producer_index++] = 'R';
}
}
else if (product == 'B')
{
if (last_char == 'R' || last_char == '\0')
{
producer_array[producer_index++] = 'B';
}
}
pthread_mutex_unlock(&producer_mutex);
}
return NULL;
}
void* consumer(void* arg)
{
while (consumer_index < BUFFER_SIZE)
{
pthread_mutex_lock(&consumer_mutex);
while (consumer_index < BUFFER_SIZE)
{
char last_c_char = (consumer_index > 0) ? consumer_array[consumer_index - 1] : '\0';
pthread_mutex_lock(&producer_mutex);
char last_p_char = (producer_index > 0) ? producer_array[producer_index - 1] : '\0';
if ((last_c_char == 'B' && last_p_char == 'G') ||
(last_c_char == 'G' && last_p_char == 'R') ||
(last_c_char == 'R' && last_p_char == 'B') ||
(last_c_char == '\0' && last_p_char == 'B'))
{
consumer_array[consumer_index++] = producer_array[--producer_index];
}
pthread_mutex_unlock(&producer_mutex);
if (consumer_index >= BUFFER_SIZE) {
break;
}
}
pthread_mutex_unlock(&consumer_mutex);
usleep(1); // Allow other threads to acquire the mutex
}
return NULL;
}