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
{
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);
}
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