[cpp-threads] Re: Comments on N2094 MT API proposal

Anthony Williams anthony at justsoftwaresolutions.co.uk
Fri Sep 15 16:57:04 BST 2006


"Peter Dimov" <pdimov at mmltd.net> writes:

> To: C++ extensions mailing list
> Message c++std-ext-7976
>
> I'm saying that "while( trylock ) yield;" loops are broken.

> "while( !trylock ) sleep;" loops (boost::detail::lightweight_mutex used
> that) are also broken for a different reason; they can lead to "oversleep"
> which degrades performance substantially (by an order of magnitude in some
> circumstances).

Yes. This is a busy wait, and the yield or sleep is just a smokescreen that
hides this fact, whilst potentially degrading the performance of the waiting
thread. My point was that if we provide a trylock of any kind, without the
corresponding blocking lock, then people will be tempted to write a busy wait
loop like this, which is not only bad in general, but in the particular case
of upgrading a sharable lock can lead to deadlock.

If we feel that the blocking operation is unsafe, we shouldn't provide the
non-blocking variety.

I feel that everywhere people will want to write a busy wait loop like this,
we should provide a blocking op. condition variables are the general purpose
tool for the job, but they require cooperation from the source of the "event".
I find it irritating when there are event sources that require polling.

>> Why are you presuming that yield() wouldn't yield to lower priority
>> threads? Surely that would be one of the reasons to call it?
>
> I have to presume one way or the other. Howard's prototype maps yield to
> sched_yield, which doesn't yield to lower priority threads. It can be useful
> in some limited cases on an uniprocessor, but the algorithm must not rely on
> yield not being a no-op for correctness, only for performance.

The POSIX spec for sched_yield doesn't say much about which threads are
yielded to:

"The sched_yield() function shall force the running thread to relinquish the
processor until it again becomes the head of its thread list."

so we can't assume either way. The nearest equivalent on Windows is Sleep(0),
which doesn't yield to lower priority threads, and YieldProcessor(), which
isn't even guaranteed to yield to other threads of higher priority.

> We are obviously free to redefine our yield any way we like. However, if the
> only way to implement our specification of yield is to use sleep, it becomes
> oversleep-prone.

Agreed. The only need I have for yield is for polling event sources that don't
allow a wait. In these cases, I'm really not sure what to code in preference
to:

while(!event_triggered()) Sleep(1);

on Windows, which is potentially prone to oversleep, as you say --- even
waiting only a millisecond between polls can be too long.

Anthony
-- 
Anthony Williams
Software Developer
Just Software Solutions Ltd
http://www.justsoftwaresolutions.co.uk



More information about the cpp-threads mailing list