#include #include #include #include #define BUFFER_SIZE 5 #define NUM_TASKS 20 int buffer[BUFFER_SIZE]; int in = 0, out = 0, count = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t not_empty = PTHREAD_COND_INITIALIZER; pthread_cond_t not_full = PTHREAD_COND_INITIALIZER; void *producer(void *arg) { for (int task = 1; task <= NUM_TASKS; task++) { pthread_mutex_lock(&mutex); while (count == BUFFER_SIZE) // buffer full pthread_cond_wait(¬_full, &mutex); // produce buffer[in] = task; printf("[Producer] Produced task %d at index %d\n", task, in); in = (in + 1) % BUFFER_SIZE; count++; pthread_cond_signal(¬_empty); pthread_mutex_unlock(&mutex); usleep(100000); // just to see interleaving } // send a special task = -1 to indicate completion pthread_mutex_lock(&mutex); while (count == BUFFER_SIZE) pthread_cond_wait(¬_full, &mutex); buffer[in] = -1; in = (in + 1) % BUFFER_SIZE; count++; pthread_cond_signal(¬_empty); pthread_mutex_unlock(&mutex); return NULL; } void *consumer(void *arg) { while (1) { pthread_mutex_lock(&mutex); while (count == 0) // buffer empty pthread_cond_wait(¬_empty, &mutex); int task = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; pthread_cond_signal(¬_full); pthread_mutex_unlock(&mutex); if (task == -1) { printf("[Consumer] Received termination signal. Exiting.\n"); break; } printf("[Consumer] Processing task %d\n", task); usleep(150000); } return NULL; } int main() { pthread_t prod_thread, cons_thread; pthread_create(&prod_thread, NULL, producer, NULL); pthread_create(&cons_thread, NULL, consumer, NULL); pthread_join(prod_thread, NULL); pthread_join(cons_thread, NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(¬_empty); pthread_cond_destroy(¬_full); return 0; }