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

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 acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk