/* Readers/Writers Problem - Solution 2 For more details, see P.J. Corbato, F. Heymans, and D.L. Parans, Concurrent Control with Readers and Writers, Commun. of the ACM, vol. 10, pp. 6687-668. Oct. 1971 Copyright (c) 2001 Xiao Zhang */ #include #include #include #include /**********************************************************************/ /* Solution 2: Once a writer is read to write, he performs his */ /* "write" as soon as possible. Be noticed that when there are two or */ /* more than two running writers, readers will starve to death. */ /**********************************************************************/ class ReadWriteMutex { private: int rc; /* readcount */ int wc; /* writecount */ pthread_mutex_t rc_mutex; pthread_mutex_t wc_mutex; pthread_mutex_t mutex3; pthread_mutex_t r_mutex; pthread_mutex_t w_mutex; public: ReadWriteMutex() { rc = 0; wc = 0; pthread_mutex_init(&rc_mutex, NULL); pthread_mutex_init(&wc_mutex, NULL); pthread_mutex_init(&mutex3, NULL); pthread_mutex_init(&r_mutex, NULL); pthread_mutex_init(&w_mutex, NULL); } void read_lock() { pthread_mutex_lock(&mutex3); pthread_mutex_lock(&r_mutex); pthread_mutex_lock(&rc_mutex); rc++; if (rc == 1) pthread_mutex_lock(&w_mutex); pthread_mutex_unlock(&rc_mutex); pthread_mutex_unlock(&r_mutex); pthread_mutex_unlock(&mutex3); } void read_unlock() { pthread_mutex_lock(&rc_mutex); rc--; if (rc == 0) pthread_mutex_unlock(&w_mutex); pthread_mutex_unlock(&rc_mutex); } void write_lock() { pthread_mutex_lock(&wc_mutex); wc++; if (wc == 1) pthread_mutex_lock(&r_mutex); pthread_mutex_unlock(&wc_mutex); pthread_mutex_lock(&w_mutex); } void write_unlock() { pthread_mutex_unlock(&w_mutex); pthread_mutex_lock(&wc_mutex); wc--; if (wc == 0) pthread_mutex_unlock(&r_mutex); pthread_mutex_unlock(&wc_mutex); } }; /**********************************************************************/ /* Below is the program for testing the above protocol. */ /* We create several readers which read `current_time' and writers */ /* which set `current_time'. */ /**********************************************************************/ #define READERS 4 #define WRITERS 4 ReadWriteMutex rw_mutex; int current_time; int ready = 0; pthread_mutex_t ready_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t ready_cond = PTHREAD_COND_INITIALIZER; int go = 0; pthread_mutex_t go_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t go_cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t screen = PTHREAD_MUTEX_INITIALIZER; void ready_to_go() { pthread_mutex_lock(&ready_mutex); ready++; pthread_mutex_unlock(&ready_mutex); pthread_cond_signal(&ready_cond); pthread_mutex_lock(&go_mutex); while (go == 0) pthread_cond_wait(&go_cond, &go_mutex); pthread_mutex_unlock(&go_mutex); } void *reader(void *arg) { ready_to_go(); int i,j; for (i = 0; i < 100; i++) { int local_time; rw_mutex.read_lock(); for (j = 0; j < 1000000; j++) local_time = current_time; /* screen lock is necessary for readers because multiple readers can print simultanously. */ pthread_mutex_lock(&screen); cout << pthread_self() << ":" << i << ": read current_time = " << local_time << endl; pthread_mutex_unlock(&screen); rw_mutex.read_unlock(); } return NULL; } void *writer(void *arg) { ready_to_go(); int i,j; for (i = 0; i < 100; i++) { rw_mutex.write_lock(); for (j = 0; j < 100000; j++) current_time = time(0); cout << pthread_self() << ":" << i << ": write current_time = " << current_time << endl; rw_mutex.write_unlock(); } return NULL; } int main() { int i; pthread_t rid[READERS], wid[WRITERS]; for (i = 0; i < READERS; i++) pthread_create(&rid[i], NULL, reader, NULL); for (i = 0; i < WRITERS; i++) pthread_create(&wid[i], NULL, writer, NULL); pthread_mutex_lock(&ready_mutex); while (ready != READERS + WRITERS) pthread_cond_wait(&ready_cond, &ready_mutex); pthread_mutex_unlock(&ready_mutex); go = 1; pthread_cond_broadcast(&go_cond); for (i = 0; i < READERS; i++) pthread_join(rid[i], NULL); for (i = 0; i < WRITERS; i++) pthread_join(wid[i], NULL); return 0; }