Can someone please review my rwlock implementation to see if there are any issues with correctness (hopefully not), give any feedback on how to write good C code etc, design patterns which could be useful.
struct rwlock{
pthread_cond_t read_var;
pthread_cond_t write_var;
pthread_mutex_t mutex;
int readers = 0; // no of readers
int writers = 0; // no of writers
int read_waiters = 0; // no of waiters for reading while writing
int write_waiters = 0; // no of waiters for writing while reading
};
void rd_lock(struct rwlock * lock){
// if we are not writing, simply get the lock
// if we are writing, increase the number of read_waiters and wait for signal
pthread_mutex_lock(&lock->mutex);
if(lock->writers == 0){
lock->readers++;
} else if(lock->writers > 0){
lock->read_waiters++;
while(pthread_cond_wait(&read_var,&mutex) != 0 && lock->writers > 0 );
// if we have returned
lock->read_waiters--;
lock->readers++;
}
pthread_mutex_unlock(&lock->mutex);
}
void wr_lock(struct rwlock * lock){
// if we are not readers, simply get the lock
pthread_mutex_lock(&lock->mutex);
if(lock->readers == 0){
lock->writers = 1;
} else if(lock->readers > 0){
// if we are readers, simply increase the number of write_waiters and wait for signal
lock->write_waiters++;
while(pthread_cond_wait(&write_var,&mutex) != 0 && lock->readers > 0);
// we have the mutex and lock->readers = 0
lock->write_waiters--;
lock->writers = 1;
} else {
assert(false);
}
pthread_mutex_unlock(&lock->mutex);
}
void unlock(struct rwlock * lock){
pthread_mutex_lock(&lock->mutex);
// if we are reading, decrease the number of readers if the readers becomes zero then broadcast to writers
if(lock->readers > 0){
lock->readers--;
if(lock->readers == 0){
assert(lock->read_waiters == 0);
// if we are releasing the readlock completely, at this point read_waiters should be zero
// broadcast to writers only if there are writers
if(lock->write_waiters > 0){
pthread_cond_broadcast(&lock->write_var);
}
}
} else if(lock->readers == 0) {
// we were writing
lock->writers = 0;
// we need to completely release the lcok now
// either the readers are going to get it or the writers are going to get it
// give priority to the writers
// obviously readers should be zero
if(lock->write_waiters > 0){
pthread_cond_broadcast(&lock->write_var);
} else if(lock->read_waiters > 0){
pthread_cond_broadcast(&lock->read_var);
}
} else {
assert(false);
}
```
int readers = 0; // no of readers==> Since when did this become Standard C? Are you compiling under a C++ compiler? \$\endgroup\$