Implementing reader-writers lock using basic pthread objects and methods

35 Views Asked by At

I wish to implement a naive reader-writers lock using the basic primitives and thier respective methods that are in the pthread library (i.e. - <pthread.h>).

I went over couple of questions and thier answers but neither satisfied what I was looking for:

This, and this, also this, and finally this as well

It is mainly for educational purposes, I guess that there are built-in mechanisms for this kind of need nowadays.

1

There are 1 best solutions below

1
Guy Avraham On

The below implementation is the very basic solution I came up with:

#include <pthread.h>

typedef struct {
    pthread_mutex_t mutex;
    pthread_cond_t cond_readers;
    pthread_cond_t cond_writers;
    int readers;
    int writers;
} rw_lock;

void rw_lock_init(rw_lock *lock) {
    lock->readers = 0;
    lock->writers = 0;
    pthread_mutex_init(&lock->mutex, NULL);
    pthread_cond_init(&lock->cond_readers, NULL);
    pthread_cond_init(&lock->cond_writers, NULL);
}

void rw_lock_acquire_read(rw_lock *lock) {
    pthread_mutex_lock(&lock->mutex);
    while (lock->writers > 0) {
        pthread_cond_wait(&lock->cond_readers, &lock->mutex);
    }
    lock->readers++;
    pthread_mutex_unlock(&lock->mutex);
}

void rw_lock_release_read(rw_lock *lock) {
    pthread_mutex_lock(&lock->mutex);
    lock->readers--;
    if (lock->readers == 0) {
        pthread_cond_broadcast(&lock->cond_writers);
    }
    pthread_mutex_unlock(&lock->mutex);
}

void rw_lock_acquire_write(rw_lock *lock) {
    pthread_mutex_lock(&lock->mutex);
    while (lock->readers > 0 || lock->writers > 0) {
        pthread_cond_wait(&lock->cond_writers, &lock->mutex);
    }
    lock->writers++;
    pthread_mutex_unlock(&lock->mutex);
}

void rw_lock_release_write(rw_lock *lock) {
    pthread_mutex_lock(&lock->mutex);
    lock->writers--;
    pthread_cond_broadcast(&lock->cond_writers);
    pthread_cond_broadcast(&lock->cond_readers);
    pthread_mutex_unlock(&lock->mutex);
}

void rw_lock_destroy(rw_lock *lock) {
    pthread_mutex_destroy(&lock->mutex);
    pthread_cond_destroy(&lock->cond_readers);
    pthread_cond_destroy(&lock->cond_writers);
}

Notes about this implementation: It gives priority to the readers before writers.

The way to overcome it can be as follows:

In the void rw_lock_release_read(rw_lock *lock) method, the "signaling" when there are no readers left, should be change so that it will signal to a particular writer usiung the writers' condition variable, like so:

if (lock->readers == 0) {
    pthread_cond_signal(&lock->cond_writers); // Signal waiting writers first
}

While in addition, the rw_lock_release_write(rw_lock *lock) method should be changed as follows:

void rw_lock_release_write(rw_lock *lock) {
    pthread_mutex_lock(&lock->mutex);
    lock->writers--;
    if (lock->writers == 0) {
        pthread_cond_broadcast(&lock->cond_readers); // Signal waiting readers second
    }
    pthread_cond_signal(&lock->cond_writers); // Signal waiting writers first
    pthread_mutex_unlock(&lock->mutex);
}

If there are any comments on the solutions I would be glad to know about them!