379_demos/lab6/demos/monitor.c

95 lines
2.4 KiB
C

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
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);
}