I’m having trouble understanding why the solution to this problem may starve readers. If you have reader and writer threads waiting for a write lock, the writer threads have no advantage. Either type could be the next one to grab the write lock and execute.
20.7 The readers writers problem with write preference
goal
#2
I also agree that it cannot specifically starve a reader. But it has another problem; when writer 1 is writing and writer 2 arrives and then reader 3 arrives, this algorithm cannot guarantee that writer 2 will write before reader 2 reads. This essentially means that any task can starve irrespective of whether it is reader or writer.
A solution will be getting the incoming task in a queue and do the operation in FIFO order. I have the following code working for me:
void Dispatcher(queue<RWEnum>& q)
{
while(true) {
RWEnum task;
bool got = false;
{
unique_lock<mutex> u_lock(RW::q_mutex);
if(!q.empty()) {
task = q.front();
got = true;
}
}
if (got) {
if(task == RWEnum::READ) {
{
unique_lock<mutex> u_lock(RW::rw_mutex);
if(!RW::writing) {
++RW::reader_count;
thread(Reader).detach();
{
lock_guard<mutex> lg(RW::q_mutex);
q.pop();
}
} else {
while(RW::writing) {
RW::convar_rw.wait(u_lock);
}
}
}
}
else if(task == RWEnum::WRITE) {
{
unique_lock<mutex> u_lock(RW::rw_mutex);
if(!RW::writing && RW::reader_count == 0) {
RW::writing = true;
thread(Writer).detach();
{
lock_guard<mutex> lg(RW::q_mutex);
q.pop();
}
} else {
while(RW::writing || RW::reader_count != 0) {
RW::convar_rw.wait(u_lock);
}
}
}
}
}
{
unique_lock<mutex> q_lock(RW::q_mutex);
if(q.empty()) {
RW::convar_empty_queue.wait(q_lock);
}
}
}
}
0 Likes