Boost logo

Boost :

From: Jens Maurer (Jens.Maurer_at_[hidden])
Date: 2001-09-17 16:04:56


williamkempf_at_[hidden] wrote:
>
> --- In boost_at_y..., Jens Maurer <Jens.Maurer_at_g...> wrote:
> > I think this patch (nearly) does what you want. It uses a similar
> > trick than the Windows variant, but doesn't spread the mutex
> contention.
>
> After looking closer at the proposed patch this simply won't work.
> The Win32 implementation uses the DCL pattern, which for IA32
> implementations is safe, so I'm not as concerned there. But for
> POSIX this implementation is going to run on architectures that use
> aggressive reordering and the DCL simply isn't thread safe in that
> case.

One of the intents of Boost.Thread should be to show limitations of
the current C++ memory model, and this certainly is one. Of course,
Boost.Thread also has to assume "correct" memory ordering when
using synchronization primitives, e.g. changes performed in
a given critical section on one CPU need to be globally visible
when the next CPU enters that critical section.

In the particular case with call_once(), the only problem happens
when we transition "flag" back from true -> false, i.e. when an
exception happened. If no exception happens, other CPUs could
still believe "flag" is false, enter the critical section, find
out "flag" is true in reality (since we must assume that a
critical section has proper memory ordering), and all is well.

If an exception happened and "flag" transitions from true -> false,
other CPUs could still believe that "flag" is true and avoid
re-executing the target function. That's a race.

The easy way to avoid that is to document that the target function
of "call_once()" may not throw exceptions, or that it is considered
executed even if it throws an exception. I'm not sure which option
is more useful.

> (Even worse is the fact that the patch uses a
> global mutex for all calls, which would add significantly more
> overhead still, even on platforms that don't require memory barriers,
> but there is a way to eliminate this problem.)

There's only more overhead if there's lock contention, i.e. lots
of call_once() (probably for different target functions) going on at
the same time. How broad is the usage potential of pthread_once()
(or call_once), anyway?

Jens Maurer


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