96 lines
2.4 KiB
C
96 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);
|
||
|
}
|