I am currently reading a book about multi threading in C++. In one chapter I found some source code for a thread safe queue. It is roughly built like this:
template<typename T>
class QueueThreadSafe
{
private:
std::mutex m_mutex;
std::queue<T> m_dataQueue;
std::condition_variable m_dataCondition;
public:
void push(T someValue)
{
std::lock_guard<std::mutex> guard(m_mutex);
m_dataQueue.push(someValue);
m_dataCondition.notify_one();
}
void pop(T &retVal)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_dataCondition.wait(lock, [this]{return !m_dataQueue.empty();});
retVal = m_dataQueue.front();
m_dataQueue.pop();
}
};
When a value is pushed to the queue, a data condition is notified and some (possible) waiting thread in pop can resume working. What confuses me are spurious wakes in this scenario. What if, at the same time one thread is notified, another thread just wakes up at the same time? Of course he also sees a not empty queue. In this scenario, two different threads would try to pop a value, where possibly only one value exists - a classical race condition.
Did I miss something here? Is there a better way to do this?