Boost logo

Boost Users :

Subject: [Boost-users] [Thread] Writer/Reader strange scheduling
From: Gaetano Mendola (mendola_at_[hidden])
Date: 2010-08-10 07:11:30


Hi all,
I'm in need to have a reader/writer mutex with no starvation (I'd say a fair
mutex), before to make a my own implementation I have checked the boost one
to see if it makes starvation or not, and I'm a bit puzzled about the behave:

I'm experiencing this:

reader 1 start
 ... writer 1 running ...
reader 2 start
 ... writer 2 running ...
writer 1 start << blocked
reader 3 start << blocked
reader 4 start << blocked

until now it seems that reader 3 and reader 4 are waiting because there is a
writer waiting and then the writer will run before reader 3 and 4, unfortunately
this is not the case, the execution continues like this:

reader 1 ends
reader 2 ends
 ... writer 3 running ...
 ... writer 4 running ...
reader 3 ends
reader 4 ends
 ... writer 1 running ...
writer 1 ends

isn't that a waste? Why make reader 3 and 4 waiting and then make those running
before the writer? The code to reproduce that is at the end.

Regards
Gaetano Mendola

#include <iostream>
#include <boost/thread.hpp>

typedef boost::shared_mutex TMutex;
TMutex theMutex;

struct Writer
{
  Writer(const size_t anId) : theId(anId) { }

  void operator()() {
    std::cout << "writer " << theId << " start" << std::endl;
    boost::unique_lock<TMutex> myLock(theMutex);
    std::cout << " ... writer " << theId << " running ..." << std::endl;
    ::sleep(7);
    std::cout << "writer " << theId << " ends" << std::endl;
  }

  size_t theId;
};

struct Reader
{
  Reader(const size_t anId) : theId(anId) { }

  void operator()() {
    std::cout << "reader " << theId << " start" << std::endl;
    boost::shared_lock<TMutex> myLock(theMutex);
    std::cout << " ... writer " << theId << " running ..." << std::endl;
    ::sleep(7);
    std::cout << "reader " << theId << " ends" << std::endl;
  }

  size_t theId;
};

int main (int argc, char** argv)
{

   Reader r1(1), r2(2), r3(3), r4(4);
   Writer w(1);

   boost::thread myR1(boost::ref(r1));
   ::sleep(1);
   boost::thread myR2(boost::ref(r2));
   ::sleep(1);
   boost::thread myW1(boost::ref(w));
   ::sleep(1);
   boost::thread myR3(boost::ref(r3));
   ::sleep(1);
   boost::thread myR4(boost::ref(r4));

   myW1.join();
   myR1.join();
   myR2.join();
   myR3.join();
   myR4.join();
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net