Boost logo

Boost :

From: William E. Kempf (wekempf_at_[hidden])
Date: 2003-06-07 13:25:32

Stefan Seefeld said:
> William E. Kempf wrote:
>>>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)

I can't elaborate easily, especially with out reference code.

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

As soon as synchronization relies on *BOTH* a mutex and a sema/event,
you've got a race condition.

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

The semaphore only represents a logical count... the queue holds the
actual count (even if it's not publicly available). That's why you use a
mutex in your code... to protect the actual shared state. Semas/events
are only useful when the count/flag is the *only* state. Otherwise, you
have more synchronization to do, which can be very tricky to do with out
race conditions.

William E. Kempf

Boost list run by bdawes at, gregod at, cpdaniel at, john at