Re: Threading issue in next standard
Maciej Sobczak wrote:
Object *p = new Object();
// set up the new object
mtx.lock();
queue.push(p);
mtx.unlock();
above, the object in question was created and constructed *outside* of
the scope of mutex, and the mutex itself is only guarding the queue's
internal stuff. If you associate the mutex with the queue only (and
that's the only thing you can statically declare), then consumers will
see the new pointer in the queue, but not necessarily the object that it
points to. (On the other, hand, if you try to extend the scope of mutex
to cover also the object's construction, it might increase contention.)
I have a ProdConQueue template which is basically what you are
implementing here. Now its push() method does the locking for you so
it's pretty similar to what you have there.
Above you are pushing a pointer onto the queue. The thread that does
the pushing is not going to call delete so I don't see the problem. If
you pushed shared_ptr<Object> then it would be important that the
reference counting is thread-safe because both threads might lose their
last reference at the same time. That would be a problem, incidentally,
only after the consumer thread has popped it off the queue. As long as
its in the queue there is at least one reference to it. The locking
ensures that.
Note that above, the pointer indirection might not be so explicit. Think
about std::queue of std::strings. Or std::queue of Persons, where Person
has some std::string attributes.
If the string is implemented with copy-on-write then again the problem
would occur after the consumer thread has taken it off the queue. Until
then, nobody is going to write to the string, and the queue will ensure
that it increments the reference count before the producer lets go.
If string is not implemented with copy-on-write there should be no
thread issues at all as both threads are working with different copies.
Of course, we might as well drop our habits and accommodate some new
ones. Hell, we're going to do this anyway. ;-)
Along with ProdConQueue I have a ConsumerThread class. I thought it
would be a pretty "standard" behaviour but actually I have 3 different
behaviours. My ProdConQueue class allows multiple pushes and pops,
(called insert and flush). These lock once then add or remove multiple
items at a time. flush commonly used where I have just one consumer
thread. Yet my two instances of threads that flush both have different
behaviour - one splits it into individual items and processes them one
at a time, the other one processes the whole lot together.
My pop() and flush() functions also both come with timed_wait options.
Does the consumer-thread use a timed-wait or not? Again specific to
requirements.
I would be interested to see how other producer-consumer queues have
been implemented and how they compare to mine.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]