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