0

I have some objects defined as global, which means their constructor are entered before program start or under DllMain(). This causes some issues, and that is why I want to move them to local static.

Our main project are mainly under Visual Studio 2012. According to the these post.

The Magic Statics is not implemented in Visual Studio 2012 (until VS 2015). So the local static variable initialization is not automatically protected from concurrent access by compiler.

What is a suitable workaround or solution for this case?


Here is what I tried:

Add a lock to protect. But if the variable initialized before the function is entered, my lock may be useless...

// data object
struct Cat
{
    Cat()
    {
        std::cout << __FUNCTION__ <<  "\n";
    }
};

// lock mutex for singleton getter
static std::mutex getcat_m;

// singleton getter
Cat& GetCat(){
    std::cout << __FUNCTION__ <<  " In\n";

    std::lock_guard<std::mutex> lk(getcat_m);
    static Cat cat;

    std::cout << __FUNCTION__ <<  " Out\n";
    return cat;
}

int main(int argc, char* argv[])
{
    std::cout << __FUNCTION__ <<  " In\n";
    Cat& cat = GetCat();
    std::cout << __FUNCTION__ <<  " Out\n";

    std::cin.ignore();
    return 0;
}

It actually shows as expected. The constructor is called after function is entered.

main In
GetCat In
Cat::Cat
GetCat Out
main Out

But I am not sure whether this is a suitable solution.

Chen OT
  • 2,945
  • 2
  • 19
  • 38
  • 1
    You can also give `std::call_once` a try. Looks like it's also reccommended [18.2.4 Use std::call_once rather than the Double-Checked Locking pattern](http://www.codingstandard.com/rule/18-2-4-use-stdcall_once-rather-than-the-double-checked-locking-pattern/) – Mihayl Dec 06 '17 at 07:10

1 Answers1

0

Thanks to A. A in comment for the link 18.2.4 Use std::call_once rather than the Double-Checked Locking pattern.

I referenced the example from the Guildline, and rewrite my singleton getter code as the following.

// Cat.cpp
static std::once_flag once_Cat;
static Cat* gpCat = nullptr;
void init_Cat() { gpCat = new Cat(); }

Cat& GetCat() {
    std::call_once(once_Cat, init_Cat);
    return *gpCat;
}
Chen OT
  • 2,945
  • 2
  • 19
  • 38