Re: using std::queue with two threads
hongseok.yoon@gmail.com wrote in news:1186988762.969071.191410
@x40g2000prg.googlegroups.com:
I've two threads and one thread only write to std::queue using push()
function and another thread only read from std::queue using front()
and pop() functions.
If I suppose to use no mutex, is the queue thread-safe?
Not only is this not safe, but also std::queue presents the wrong
interface for any general purpose thread-safe queue because std::queue
exposes so many fine-grained interfaces. Even if a thin-locking
interface is added, where each method is locked, it would not really
be thread-safe if there's more than one queue consumer. Consider when
two consumers are popping off items:
C1: if (size()) { front(), pop() }
C2: if (size()) { front(), pop() }
Any one of those "locked" functions could be interspersed with
operations in another thread.
A mutex-based solution would likely present a pop that wraps multiple
operation. Consider the following:
#include <queue>
#include <boost/bind.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
template <typename T>
class ts_queue
{
std::queue<T> q;
boost::mutex m;
boost::condition c;
public:
bool try_pop(T & value)
{
boost::mutex::scoped_lock sl(m);
if (q.size())
{
value = q.front();
q.pop();
return true;
}
return false;
}
// could block forver
T pop()
{
boost::mutex::scoped_lock sl(m);
while (1)
{
c.wait(sl, boost::bind(&std::queue<T>::size, q));
T value = q.front();
q.pop();
return value;
}
}
};
The interface presents the basic consumer operations wrapped for
safety. The second, pop(), is probably not really what you want to
do. You might want to have more options, like a cancellation
function, etc.
If lock-free is more your speed, get yourself a lock-free
implementation of a queue. Or implement one from the published
papers.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]