diff --git a/lab6/demos/monitor.c b/lab6/demos/monitor.c new file mode 100644 index 0000000..82ba28a --- /dev/null +++ b/lab6/demos/monitor.c @@ -0,0 +1,95 @@ +#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); +}