so what ? the 'real' queue length is kept private and doesn't matter much. It's the signaling of the semaphore that makes the change public.
This is a race condition. It also occurs when extracting data from the queue. Whether or not the "'real' queue length" is private is not relevant, this race condition can lead to improper synchronization, such as trying to to extract data when there's no data left to extract.
Can you elaborate ? I can manipulate the queue as much as I want, the availability of tasks will be known to consumers only when they are signaled, not when the queue is non-empty. Where is the race condition ? (Same argument for the empty slots)
Oh, of course the queue needs a mutex, too (as I said in my original mail), just to protect the queue's internal structure, so a task extraction may look like that:
template <typename T> T task_queue::consume() { my_tasks.wait(); // decrements 'tasks' counter Prague::Guard<Mutex> guard(my_mutex); // protects queue impl T t = rep_type::front(); // copies next task (mustn't throw !) rep_type::pop(); // removes task from queue impl my_free.post(); // announce availability of a free slot return t; // return t }
The only tricky thing here is to make sure T's copy constructor doesn't throw.
And then there is the other semaphore I use to count the free slots, which you didn't comment on, probably because it didn't fit into your arguments...
No, actually, it strengthens the argument, because you now have even more state that needs to be synchronized to ensure against race conditions.
I don't understand this. The state in question is the difference between the capacity of the queue and its current length. The only variable holding this state is the semaphore ('my_free' in my code snippet). What do I need to synchronize here ?
Regards, Stefan
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost