/* * Monitor-based implementation of readers/writers. * * Gives priority to readers, so writers could starve. * * (Solution adapted from various online sources.) */ #include #include #include #include #include "test-readers-writers.h" #include "readers-writers.h" /* global variables for synchronization */ int readers = 0; bool writer = false; int readers_waiting = 0; pthread_mutex_t monitor_mutex; pthread_cond_t can_read; pthread_cond_t can_write; void init_synch(void) { pthread_mutex_init(&monitor_mutex, NULL); pthread_cond_init(&can_read, NULL); pthread_cond_init(&can_write, NULL); } void end_synch(void) { pthread_mutex_destroy(&monitor_mutex); pthread_cond_destroy(&can_read); pthread_cond_destroy(&can_write); } void simulate_read_with_synch(const int readerID, const int delay) { /* begin_read() */ pthread_mutex_lock(&monitor_mutex); /* * "while" not "if" because POSIX implementation of condition * variables sometimes generates spurious signals. */ while (writer) { readers_waiting += 1; pthread_cond_wait(&can_read, &monitor_mutex); readers_waiting -= 1; } readers += 1; pthread_cond_signal(&can_read); pthread_mutex_unlock(&monitor_mutex); simulate_read(readerID, readers, delay); /* end_read() */ pthread_mutex_lock(&monitor_mutex); readers -= 1; if (readers == 0) { pthread_cond_signal(&can_write); } pthread_mutex_unlock(&monitor_mutex); } void simulate_write_with_synch(const int writerID, const int delay) { /* begin_write() */ pthread_mutex_lock(&monitor_mutex); /* * "while" not "if" because POSIX implementation of condition * variables sometimes generates spurious signals. */ while (writer || (readers > 0)) { pthread_cond_wait(&can_write, &monitor_mutex); } writer = true; pthread_mutex_unlock(&monitor_mutex); simulate_write(writerID, delay); /* end_write() */ pthread_mutex_lock(&monitor_mutex); writer = false; if (readers_waiting > 0) { pthread_cond_signal(&can_read); } else { pthread_cond_signal(&can_write); } pthread_mutex_unlock(&monitor_mutex); }