I am designing an asynchronous logger class as follows. However, not sure if I am using the boost condition variable in the right way. Can anyone comment on this? Here the processLogEntry method is a thread function and I am using boost here.
void LogWriter::stopThread()
{
mStop = true;
mCond.notify_one();
mThread->join();
}
void LogWriter::processLogEntry()
{
while(!mStop)
{
boost::mutex::scoped_lock lock(mMutex);
mCond.wait(lock);
while(!q.empty())
{
// process begins
}
}
}
void LogWriter::addLogEntry()
{
boost::mutex::scoped_lock lock(mMutex);
// add it in the queue
mCond.notify_one();
}
As it has been pointed out, you must either make mStop atomic or guard all its accesses with the mutex. Forget about volatile, it's not relevant to your purposes.
Furthermore, when waiting on a condition variable a call to wait may return even if no notification functions were called (those are so-called spurious wake-ups). As such, calls to wait need to be guarded.
void LogWriter::stopThread()
{
{
boost::mutex::scoped_lock lock(mMutex);
mStop = true;
mCond.notify_one();
}
mThread->join();
}
void LogWriter::processLogEntry()
{
for(;;) {
boost::mutex::scoped_lock lock(mMutex);
// We wait as long as we're not told to stop and
// we don't have items to process
while(!mStop && q.empty()) mCond.wait(lock);
// Invariant: if we get here then
// mStop || !q.empty() holds
while(!q.empty())
{
// process begins
}
if(mStop) return;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With