#include #include #include // Function prototypes int make_new_item(void); void *reader_function(void *); void writer_function(void); // Shared resources char buffer; int buffer_has_item = 0; pthread_mutex_t mutex; pthread_cond_t cond_buffer_empty; pthread_cond_t cond_buffer_full; void cleanup_resources() { pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond_buffer_empty); pthread_cond_destroy(&cond_buffer_full); } int main(int argc, char *argv[]) { pthread_mutexattr_t mutex_attr; pthread_attr_t attr; pthread_t reader; int ret; // Initialize mutex and condition variables pthread_mutexattr_init(&mutex_attr); pthread_mutex_init(&mutex, &mutex_attr); pthread_cond_init(&cond_buffer_empty, NULL); pthread_cond_init(&cond_buffer_full, NULL); pthread_attr_init(&attr); // Create reader thread pthread_create(&reader, &attr, reader_function, 0); // Run writer function in the main thread writer_function(); // Wait for reader thread to finish pthread_join(reader, 0); // Clean up cleanup_resources(); printf("Main thread finished!\n"); return 0; } void writer_function(void) { char a = 0; while (a != 'q') { pthread_mutex_lock(&mutex); // Wait until the buffer is empty while (buffer_has_item) { pthread_cond_wait(&cond_buffer_empty, &mutex); } a = make_new_item(); buffer = a; buffer_has_item = 1; printf("Thread 1: buffer: '%c'\n", a); // Signal the reader that the buffer is full pthread_cond_signal(&cond_buffer_full); pthread_mutex_unlock(&mutex); } } void *reader_function(void *ptr) { char a = 0; while (a != 'q') { pthread_mutex_lock(&mutex); // Wait until the buffer is full while (!buffer_has_item) { pthread_cond_wait(&cond_buffer_full, &mutex); } // Read the item from the buffer a = buffer; if (a != 'q') { printf("Thread 2: buffer read with '%c'\n", a); } buffer_has_item = 0; // Signal the producer that the buffer is empty pthread_cond_signal(&cond_buffer_empty); pthread_mutex_unlock(&mutex); } printf("Reader thread finished\n"); return 0; } int make_new_item() { static int buffer = 'a'; return buffer++; }