Boost logo

Boost Users :

From: Moshe Matitya (Moshe.Matitya_at_[hidden])
Date: 2006-09-18 06:57:03


Daniel F. Savarese wrote:
> ...
> However, I think I have a workaround that I just finished
> testing (at least the unit tests no longer seg fault).
> If you're willing to waste some memory and add the equivalent
> of the following to oserializer
>
> private:
> static oserializer & dummy;
>
> static oserializer & _instantiate(){
> static oserializer instance;
> return instance;
> }
> public:
> static oserializer & instantiate(){
> return dummy;
> }
>
> and to iserializer:
>
> private:
> static iserializer & dummy;
>
> static iserializer & _instantiate(){
> static iserializer instance;
> return instance;
> }
> public:
> static iserializer & instantiate(){
> return dummy;
> }
>
> and initialize oserializer::dummy as:
> template<class Archive, class T> oserializer<Archive,T> &
> oserializer<Archive,T>::dummy =
> oserializer<Archive,T>::_instantiate();
>
> and iserializer::dummy as:
> template<class Archive, class T> iserializer<Archive,T> &
> iserializer<Archive,T>::dummy =
> iserializer<Archive,T>::_instantiate();
>
> then the local static will be initialized at program initialization
> before any threads are running without incurring the global variable
> initialization ordering problem.
> ...
> This is just a test hack, but I think the concept works.

Sorry, I don't think your idea works:

(1) What happens if the constructor or initializer of a global or static
member variable calls oserializer::instantiate(), and that variable is
initialized before oserializer::dummy is initialized? E.g.:

    struct foo
    {
        foo()
        {
            // oserializer::dummy might not be initialized yet,
            // so this can return a reference to an invalid object:
            oserializer<x,y> os = oserializer::instantiate();
            os.do_something(); // boom
        }
    };
    foo g_f;

(2) There exists no guarantee that multiple threads will not be running
at program initialization time. Threads can be started in the
constructors and initializers of global or static member variables.
E.g.:

    void thread_func()
    {
        // oserializer::dummy might not be initialized yet,
        // so this can return a reference to an invalid object:
        oserializer<x,y> os = oserializer::instantiate();
        os.do_something(); // boom again
    }

    struct bar
    {
        bar()
        {
            boost::thread t(&thread_func);
        }
    }
    bar g_b;

(Btw, if your idea really did work, then you would have just invented a
thread-safe implementation of the Singleton pattern that does not
require any thread synchronization. I don't believe that's possible.)

Moshe


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net