Saturday, October 19, 2013

A ReadWrite implementation with preference to waiting writers.

Description:  Below is an implementation of ReadWrite using Mutex and Condition Variables with preference to waiting writers. Before a read lock is given, we check if there are any writers waiting to get write lock. Similary, when a lock is released, if a writer is waiting to get the lock , preference is given to them over readers.

RwLock.h (Header File)

#include <pthread.h>


class RwLock
{
    //nreaders = 0 , indicates no. reader/writer exists.
    //nreaders > 0, indicates one or more read lock exists.
    //nreaders=-1, indicates a write lock exists.

    int nreaders;

    int nwaitwriters;
   
    pthread_mutex_t rw_mutex;

    pthread_cond_t rw_condreader;
   
    pthread_cond_t rw_condwriter;

    public:

    RwLock();

    void getReadLock();

    void getWriteLock();

    void unLock();

    ~RwLock();

       
};


RwLock.C (Implementation)

#include "RwLock.h"

RwLock :: RwLock()
{
    nreaders = 0;

    nwaitwriters = 0;

    pthread_mutex_init(&rw_mutex, NULL);   

    pthread_cond_init(&rw_condreader, NULL);

    pthread_cond_init(&rw_condwriter, NULL);
}

void RwLock :: getReadLock()
{
    //Obtain Lock.
    pthread_mutex_lock(&rw_mutex);

    //If  a WRITER exists(nreaders = -1)wait for signal from writer.
    while(-1 == nreaders || 0 < nwaitwriters)
    {
        pthread_cond_wait(&rw_condwriter, &rw_mutex);
    }

    //increment no. of readers
    nreaders++;

    pthread_mutex_unlock(&rw_mutex);       
}


void RwLock :: getWriteLock()
{
    //Obtain Lock
    pthread_mutex_lock(&rw_mutex);

    //if nreader is != 0 it means either a reader or writer is present. wait for signal from reader/writer (do it in a loop)
    while(0 != nreaders)
    {
        //Increment no. of waiting writers.
        nwaitwriters++;

        pthread_cond_wait(&rw_condreader, &rw_mutex);
       
        //Decrement no. of waiting writers.
        nwaitwriters--;
       
    }

    //set nreader = -1 indicating a writer is present.
    nreaders = -1;

    //unlock the mutex.
    pthread_mutex_unlock(&rw_mutex);
}

void RwLock :: unLock()
{
    //Obtain Lock
    pthread_mutex_lock(&rw_mutex);

    if(0 < nreaders)
    {
        //one of the readers is done. decrement readers count.
        nreaders--;

        if(0 == nreaders)
        {
            //last reader is done.

            if(0 < nwaitwriters)
            {
                //if a writer is waiting
                pthread_cond_signal(&rw_condreader);
            }
        }
    }
    else if(-1 == nreaders)
    {
        //a writer is done. set nreaders to 0 indicating no reader/writer exists.
        nreaders = 0;

        if(0 < nwaitwriters)
        {
            //if a writer is waiting.
            pthread_cond_signal(&rw_condreader);
        }
        else
        {           
            //broadcast to any waiting readers.
            pthread_cond_broadcast(&rw_condwriter);
        }
    }

    pthread_mutex_unlock(&rw_mutex);
}

RwLock :: ~RwLock()
{
    //Destroy condition variable and mutex.
    pthread_mutex_destroy(&rw_mutex);

    pthread_cond_destroy(&rw_condreader);

    pthread_cond_destroy(&rw_condwriter);
}

No comments:

Post a Comment