Boost logo

Boost :

Subject: Re: [boost] [thread] Timed waits in Boost.Thread potentially fundamentally broken on Windows (possibly rest of Boost too)
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2015-01-23 09:12:19


On 23 Jan 2015 at 16:46, Andrey Semashev wrote:

> > For reference for those pondering this option, there is no
> > possibility of missed notifications on Windows as unless you use
> > PulseEvent() (we don't), it can't happen on the win32 threading
> > model.
>
> There is, if a spurious wakeup happens. There is a window between returning
> from a wait function and re-locking the mutex. If you loop without checking
> for a condition, notifications in that window will be missed.

Not in Boost.Thread.

(Longer answer: Boost.Thread has a complex internal infrastructure of
wait objects on Windows to enable emulation of thread cancellation
amongst other things. We regularly unlock the user supplied mutex for
extended periods of time. We fix that up by more special code in the
Boost.Thread condition variable implementation. This is why mixing
std::condition_variable with Boost.Thread does not work, but the
wider point is that we don't lose notifications if Boost.Thread
primitives are used)

> > > > Option 3: We adjust Boost.Thread to return timeouts when Windows
> > > > returns a timed out status code, even if the actual time waited is
> > > > considerably lower than the time requested. Problem: some code
> > > > written for POSIX where when you ask for a timeout you always get it
> > > > may misbehave in this situation.
> > >
> > > That is simply incorrect. Why would you indicate a timeout when none
> > > occurred? This will surely break some timed code.
> >
> > Some would say that if Windows claims a timeout, we should return a
> > timeout. I suspect this is what the Dinkumware STL will do, and for
> > compatibility we may wish to match that.
>
> We're not mimicking OS behavior in Boost.Thread - that's the point of it being
> a portability layer.

The Dinkumware STL behaviour is not OS behaviour. It's one of the big
three STLs.

> The library implements standard C++ components and as
> such should behave as close to the standard as possible.

The standard says nothing about what is or is not a spurious wakeup
unfortunately.

> If Windows is not well suited for it then oh well... MS should fix
> Windows then to be more efficient.

Vista made these changes to scheduling for efficiency purposes. I
suspect Boost.Thread was written for an XP or earlier target.
 
> > > The standard description is pretty clear: return cv_status::timeout only
> > > when the timeout has expired, otherwise return cv_status::no_timeout.
> > > Boost.Thread should follow this.
> >
> > This is the current behaviour. However, and it is a big however, the
> > semantics are subtly different. On POSIX you either get your wait as
> > long as you asked or a spurious wakeup. On Windows you are ordinarily
> > getting a wait between nothing and an arbitrary higher amount than
> > requested. This is a "spurious wakeup on steroids".
>
> I don't see the difference. On POSIX, you're not guaranteed to be woken up
> exactly at the timeout either. And spurious wakeups can potentially happen as
> often as one can emit signals to the process. Granted, that usually doesn't
> happen that often, but conceptually this is not different from Windows.

My reading of
http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cond_
timedwait.html says that the timed wait may not return timed out if
abstime has not passed. Unfortunately abstime is measured against the
system clock which may arbitrarily move around, but that's the POSIX
definition.

C++ is written to use steady_clock which doesn't move around, but
otherwise I believe the guarantees are the same.

> > The key point here is that Windows spurious wakeups are occuring
> > *much* more frequently than on POSIX. This has implications for
> > battery life and plenty more.
>
> So we're talking about efficiency, not correctness as you originally stated?

Let's call it correctness of expectation of behaviour by the
community. It's why I'm asking for advice here instead of
unilaterally deciding on my own. None of the three options isn't
without unhelpful consequence.

For example, would the community be happy if on Windows timed waits
always were at least the timeout interval requested? In other words,
we guarantee that timeout intervals requested are honoured?

Niall

-- 
ned Productions Limited Consulting
http://www.nedproductions.biz/ 
http://ie.linkedin.com/in/nialldouglas/



Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk