#include #include #include typedef struct { int* buffer; int buffer_len; int buffer_cap; pthread_mutex_t mutex; pthread_cond_t not_full; pthread_cond_t not_empty; } monitor_t; volatile monitor_t monitor; monitor_t* init_monitor(int buffer_cap) { monitor_t* monitor = malloc(sizeof(monitor_t)); monitor->buffer = calloc(buffer_cap, sizeof(int)); monitor->buffer_len = 0; monitor->buffer_cap = buffer_cap; pthread_mutex_init(&monitor->mutex, NULL); pthread_cond_init(&monitor->not_full, NULL); pthread_cond_init(&monitor->not_empty, NULL); return monitor; } void destroy_monitor(monitor_t* monitor) { pthread_mutex_destroy(&monitor->mutex); pthread_cond_destroy(&monitor->not_full); pthread_cond_destroy(&monitor->not_empty); free(monitor->buffer); free(monitor); } void produce(monitor_t* monitor, int item) { pthread_mutex_lock(&monitor->mutex); while (monitor->buffer_len == monitor->buffer_cap) { pthread_cond_wait(&monitor->not_full, &monitor->mutex); } monitor->buffer[monitor->buffer_len] = item; monitor->buffer_len += 1; pthread_cond_signal(&monitor->not_empty); pthread_mutex_unlock(&monitor->mutex); } int consume(monitor_t* monitor) { pthread_mutex_lock(&monitor->mutex); while (monitor->buffer_len == 0) { pthread_cond_wait(&monitor->not_empty, &monitor->mutex); } monitor->buffer_len -= 1; int item = monitor->buffer[monitor->buffer_len]; pthread_cond_signal(&monitor->not_full); pthread_mutex_unlock(&monitor->mutex); return item; } void* producer_func(void* arg) { monitor_t* monitor = arg; for (int i = 0; i < 20; i++) { produce(monitor, i); printf("Produced item %d\n", i); } pthread_exit(NULL); } void* consumer_func(void* arg) { monitor_t* monitor = arg; for (int i = 0; i < 20; i++) { int item = consume(monitor); printf("Consumed item %d\n", item); } pthread_exit(NULL); } int main(void) { pthread_t thread_producer, thread_consumer; fprintf(stderr, "Line: %d\n", __LINE__); monitor_t* monitor = init_monitor(3); pthread_create(&thread_producer, NULL, producer_func, (void*) monitor); pthread_create(&thread_consumer, NULL, consumer_func, (void*) monitor); pthread_join(thread_producer, NULL); pthread_join(thread_consumer, NULL); destroy_monitor(monitor); }