> From: William E. Kempf [mailto:williamkempf@hotmail.com]
> Sent: 06 August 2002 16:51

> From: "Anthony Williams" <anthwil@nortelnetworks.com>
> Sent: Tuesday, August 06, 2002 9:33 AM

> > > From: Peter Dimov [mailto:pdimov@mmltd.net]
> > > Sent: 06 August 2002 15:17
> > > From: "Anthony Williams" <anthwil@nortelnetworks.com>
> > > > > From: Peter Dimov [mailto:pdimov@mmltd.net]
> > > > > Sent: 06 August 2002 14:21
> > > >
> > > > > From: "Pete Becker" <petebecker@acm.org>
> > > > > > In C++ we have automatic initialization of static objects,
> > > > > so there is
> > > > > even
> > > > > > less need for once functions.
> > > > >
> > > > > We have dynamic initialization of static mutex objects, but
> > > > > we do not have
> > > > > static initialization of mutex objects. Hello
> > > initialization order.
> > > >
> > > > On POSIX, you can statically initialize a mutex, as
> mutexes are POD.
> > > >
> > > > On Windows, mutexes are always dynamically initialized.
> > > However, you can
> > > > ensure they are only initialized once by using named mutexes.
> > > >
> > > > I am sure that other platforms have ways of achieving
> the same aim.
> > >
> > > Yes. I was talking about the Boost.Threads platform.
> >
> > 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?

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:

class Win32Mutex
{
        LONG flag;
        HANDLE mutex;

        void lazyInit()
        {
                if(!InterlockedCompareExchange(&flag,1,1)) // atomically query flag, and leave set
                {
                        HANDLE newHandle=CreateMutex(...);
                        InterlockedExchangePointer(&mutex,newHandle); // atomic update of handle
                        InterlockedExchange(&flag,1); // atomically set flag
                }
        }

public:
        Win32Mutex():flag(0){} // necessary for a mutex as a class member

        ~Win32Mutex()
        {
                if(InterlockedCompareExchange(&flag,1,1)) // atomically query flag, and leave set
                {
                        // mutex initialized
                        CloseHandle(mutex);
                }
        }

        void lock()
        {
                lazyInit();
                // ...
        }
};

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.

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

Someone else will have to think about MacOS.

Anthony