Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

using std::queue with two threads

937 views
Skip to first unread message

hongse...@gmail.com

unread,
Aug 13, 2007, 11:43:21 AM8/13/07
to
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?


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Ulrich Eckhardt

unread,
Aug 13, 2007, 2:38:56 PM8/13/07
to
hongse...@gmail.com wrote:
> 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?

No. Note that multithreading is not only about atomicity (i.e. that you
don't read things while they are temporarily inconsistent) and mutuality
(i.e. that no two writes take place at the same time) but also about
visibility (i.e. that you either see all or nothing from a former write
operation in another thread). The latter case might easily not be
guaranteed, in particular when the other thread is running on a different
CPU. Another problem would be e.g. a size counter which needs to be written
by both sides.

A totally different problem might be the underlying container which might
have to reallocate its buffers and thus move existing elements which are
accessed by a different thread. This depends on the container though, I
think the default deque<> is safe in that aspect.

Disclaimer: the C++ standard is totally silent about threads, so nothing is
guaranteed to be portable.

Uli

--
Sator Laser GmbH
Geschäftsführer: Ronald Boers, Amtsgericht Hamburg HR B62 932

Thomas Maeder

unread,
Aug 13, 2007, 2:42:10 PM8/13/07
to
hongse...@gmail.com writes:

> 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?

The langauge gives absolutely no guarantees about thread-safety (nor
does it define that term). So unless your C++ implementation gives
such a guarantee, the queue is not thread-safe.

Jim Langston

unread,
Aug 14, 2007, 12:47:50 AM8/14/07
to
<hongse...@gmail.com> wrote in message
news:1186988762.9...@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?

No, it is not thread safe. I replied to your personal e-mail with a windows
base thread safe queue that wraps std::queue. You can modify it for your
needs. The reason I e-mailed it instead of posted it here is because it's
windows specific and so may be considered OT.

W. J. La Cholter

unread,
Aug 14, 2007, 11:21:24 PM8/14/07
to
hongse...@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.

Chris Thomasson

unread,
Aug 15, 2007, 8:03:24 AM8/15/07
to
<hongse...@gmail.com> wrote in message
news:1186988762.9...@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 in any sense of the term! Humm. You mentioned that your running your
queue in a single producer/consumer environment. You can use assembly
language to implement an unbounded queue that fits within that scenario.
Here is my work on the matter:

http://appcore.home.comcast.net/

http://groups.google.com/group/comp.programming.threads/browse_frm/thread/205dcaed77941352


full source-code:

http://appcore.home.comcast.net/appcore/src/cpu/i686/ac_i686_gcc_asm.html
(ac_i686_queue_spsc_push/pop api are raw impl...)

http://appcore.home.comcast.net/appcore/src/ac_queue_spsc_c.html
(abstraction translation unit)

http://appcore.home.comcast.net/appcore/include/ac_queue_spsc_h.html
(abstraction header)


That API can be wrapped with C++. If you have any questions on how to do
that, well, feel free to fire away!

:^)

Steven E. Harris

unread,
Aug 15, 2007, 4:50:26 PM8/15/07
to
"W. J. La Cholter" <wit...@giganews.com> writes:

> 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.

For an alternative, take a look at the two_lock_queue class described
here:

http://lists.boost.org/Archives/boost/2005/10/94702.php

--
Steven E. Harris

0 new messages