Boost logo

Boost :

From: Anthony Williams (anthony_w.geo_at_[hidden])
Date: 2006-11-02 03:01:00


"Chris Thomasson" <cristom_at_[hidden]> writes:

> once() throw() : m_state(0), m_count(1) {}

> static atomic::once<foo> g_foo;
>
>
> void some_threads(...) {
> for(;;) {
> // whatever...
>
>
> foo *myfoo = g_foo.load();
> if (myfoo) {
> // use myfoo...
>
> // okay, we are finished with myfoo
> g_foo.dec();
> }
>
>
> }
> }
>
> This should be a workable solution to the static initialization problem...
>
> What do you all think?

your once<> class has a constructor, so it is therefore dynamically
initialized, rather than statically, so there is a potential race condition in
calling the constructor. Not only might multiple threads run the constructor,
but some threads might get on to the load() call before the constructor is
complete, because the constructor is running in another thread. Oh, and if the
constructor is run multiple times, when is the destructor called, and how many
times?

This is particularly apparent in

void some_thread_func()
{
    static atomic::once<foo> g_foo;

    foo *myfoo = g_foo.load();
    if (myfoo) {
    }
}

since g_foo won't be initialized until the first call. The problem still
exists for global objects, but is rarer, since it will only happen with
threads that run before main(), or as a consequence of the general
global-initialization-order problem, which is independent of threads.

Anthony

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

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