Boost logo

Boost :

From: William E. Kempf (williamkempf_at_[hidden])
Date: 2002-08-07 09:33:37


----- Original Message -----
From: "Anthony Williams" <anthwil_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Wednesday, August 07, 2002 4:06 AM
Subject: RE: [boost] Enhanced call_once()

> > From: William E. Kempf [mailto:williamkempf_at_[hidden]]
> > From: "Anthony Williams" <anthwil_at_[hidden]>
> > > > From: Peter Dimov [mailto:pdimov_at_[hidden]]
> > > > From: "Anthony Williams" <anthwil_at_[hidden]>
> > > > > > From: Peter Dimov [mailto:pdimov_at_[hidden]]
> > > > > > From: "Pete Becker" <petebecker_at_[hidden]>
> > > So with Boost.Threads, you only have dynamic mutex
> > initialization (with
> > init
> > > order problems), despite the fact that two of the three (I
> > don't know
> > > anything about MacOS) supported platforms have a mechanism
> > for avoiding
> > init
> > > order problems with Mutexes?
> >
> > Yes, because those solutions aren't easy to apply to a C++
> > class design.
> > I'm working on it, but we don't have this yet.
>
> How hard can it be?

Harder then you think.

> For win32, you just lazy init using named mutexes (named after the address
> of the mutex, and the process id, or something like that). To avoid
multiple
> calls to CreateMutex, you could use some flags, and the InterlockedXXX
> functions:

In other words, the implementation already found in boost::call_once. Yes,
I know how to do this.

[snip win32 code stuff]

> Now it doesn't matter whether the mutex is statically or dynamically
> initialized --- static objects are initialized to all zero before their
> dynamic initialization, and reinitializing the flag to zero does no harm,
as
> CreateMutex will always return the same value.

Just to be sure we're all using the same language here, when I say "static
initialization" I mean the definition stated in 3.6.2/1. This requires a
POD type. The code you posted isn't POD and can't be statically
initialized. In particular this means the call to your constructor may not
have occurred when a thread started before main attempts to call lock(), and
thus the lazyInit() will likey not get called either (though it's undefined
behavior).

> For POSIX, we can use pthread_once to lazy-init the mutex.

Which requires a statically initialized pthread_once_t, so again, the mutex
type has to be POD. (At which point you'd be better off using a statically
initialized mutex then a call to pthread_once.)

A simple implementation is trivial. However, there's some warts imposed on
the simple implementation, since it's a POD type. Those are:

* No private/protected data. The full implementation will be exposed on the
public interface. We can, however, declare this as implementation defined
making it an opaque type.

* No constructors. Minor point. You simply have to document that the only
valid construction pattern is:

static boost::static_mutex = BOOST_MUTEX_INIT;

* Compiler supplied copy and assignment operators. This is the part that
bothers me the most because copy/assignment are operations that should never
be done. Again, the best we probably can do is document it as resulting in
undefined behavior.

* The implementation must use only POD members. This one shouldn't cause
any real problems with the implementation but is still worth noting.

Bill Kempf


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