Why does author think that below part of source code leads to race?
Author says:
This design is subject to race conditions between calls to empty, front and pop if there is more than one thread removing items from the queue, but in a single-consumer system (as being discussed here), this is not a problem.
Here is the code:
template<typename Data>
class concurrent_queue
{
private:
std::queue<Data> the_queue;
mutable boost::mutex the_mutex;
public:
void push(const Data& data)
{
boost::mutex::scoped_lock lock(the_mutex);
the_queue.push(data);
}
bool empty() const
{
boost::mutex::scoped_lock lock(the_mutex);
return the_queue.empty();
}
Data& front()
{
boost::mutex::scoped_lock lock(the_mutex);
return the_queue.front();
}
Data const& front() const
{
boost::mutex::scoped_lock lock(the_mutex);
return the_queue.front();
}
void pop()
{
boost::mutex::scoped_lock lock(the_mutex);
the_queue.pop();
}
};
I think what’s confused you is that in the code you posted, there is nothing that causes a race condition. The race condition would be caused by the threads actually CALLING this code. Imagine that thread 1 checks to see if the thread is not empty. Then that thread goes to sleep for a year. One year later when it wakes up, is it still valid for that thread to assume the queue is still empty? Well, no, in the meantime, another thread could have easily come along and called pushed.