boost::condition_variable cond;
boost::mutex mutex;
//thread #1
for(;;)
{
D * d = nullptr;
while( cb.pop(d) ) //cb is a circular buffer and manage is own mutex/lock internally
{
//...do something with d
}
boost::unique_lock<boost::_mutex> lock( mutex );
cond.wait( mutex );
}
//thread #2
while(1)
{
getchar();
for( int i = 0 ; i < 1000 ; ++i )
{
cb.push(new D(i)); //one producer so no lock required
cond.notify_one(); // no lock required here ?
}
}
I am wondering if it is ok if my data container has his own lock to avoid data race, and on an other hand boost::wait use his lock/mutex mechanism as it specified by boost documentation ?
Otherwise, thread1 is the consummer, in case I have only one thread which “consumme” it seems that the lock required by wait is a little bit superfluous, isn’t it ?
EDIT: I dont’ take care about missing update.When I receive an update I update an object with the received data. I just want the fresher update, not necesarilly all the udpate
You can have as many locks as you want, but you’ll get race conditions
unless both the
popand thepushare protected by the same mutex as thewaitand thenotify(and the the lock is not freed between thedecision to wait and the actual wait). The standard idiom is:
Trying to loop on the
popin thread #1 is more complicated, at leastif you want to free the lock during processing of
d. You’d needsomething like:
It’s more complicated, and I don’t see what you’d gain from it. Just
use the usual pattern, which is known to work reliably.
FWIW: your code is full of race conditions: for starters: the
popfails in thread 1, there’s a context switch, thread 2 does the
pushand the
notify, then back to thread 1, which does thecond.wait.And waits, despite the fact that there’s something in the queue.
I might add that there is almost never any justification for types like
circular buffers to manage their own mutex locking. The granularity is
too low. The exception is if the pop instruction actually waits until
something is there, i.e. (based on
std::deque):(Note the use of
auto_ptrin the interface. Once the provider haspassed the object into the queue, it no longer has a right to access
it.)