#include #include #include #include // Function prototypes int make_new_item(void); void consume_item(char a, int count); void *reader_function(void *); void writer_function(void); // Shared resources char buffer; sem_t empty; // Tracks empty slots sem_t full; // Tracks filled slots void cleanup_resources() { sem_destroy(&empty); sem_destroy(&full); } int main(int argc, char *argv[]) { pthread_attr_t attr; pthread_t reader; // Initialize semaphores // first 0 is for shared between threads, second 0 is for the initial value // first 1 would mean that the semaphore is shared between processes sem_init(&empty, 0, 1); // Initially, buffer is empty (1 empty slot) sem_init(&full, 0, 0); // Initially, buffer is not full (0 filled slots) pthread_attr_init(&attr); pthread_create(&reader, &attr, reader_function, 0); writer_function(); pthread_join(reader, 0); cleanup_resources(); printf("Main thread finished!\n"); return 0; } void writer_function(void) { char a = 0; while (a != 'q') { sem_wait(&empty); a = make_new_item(); buffer = a; printf("Thread 1: buffer: '%c'\n", a); // Signal that the buffer is full sem_post(&full); } } void *reader_function(void *ptr) { char a = 0; while (a != 'q') { sem_wait(&full); a = buffer; if (a != 'q') { consume_item(a, 0); } sem_post(&empty); } printf("Reader thread finished\n"); return 0; } int make_new_item() { static int buffer = 'a'; return buffer++; } void consume_item(char a, int count) { printf("Thread 2: buffer read with '%c'\n", a); }