jeudi 22 mars 2018

Portable C++ Singleton - When is the destructor called

When a thread safe singleton has to be implemented using C++11 the only correct implementation I know is the following:

// header
class Singleton final {
public:
  Singleton& getInstance();

private:
  Singleton() = default;
  Singleton(Singleton const&) = delete;
  void operator=(Singleton const&) = delete;
};

// implementation:
Singleton& Singleton::getInstance() {
  static Singleton instance;
  return instance;
}

In his Book "C++ Concurrency in Action" A. Williams writes that since C++11 "the initialization is defined to happen on exactly one thread" and so this "can be used as an alternative to std::call_once" when a single global instance is required. I wounder when the destructor of the Singleton is called when defined as above.

The standard (ISO/IEC 14882:2011) defines as part of §3.6.3 e. g.

Destructors for initialized objects (that is, objects whose lifetime has begun) with static storage duration are called as a result of returning from main and as a result of calling std::exit.

and

Calling the function std::abort() declared in cstdlib terminates the program without executing any destructors and without calling the functions passed to std::atexit() or std::at_quick_exit().

I know that it is a bad idea to use a singleton that is provided by a shared library (that might be unloaded before other parts that might use it), but is that like not possible when the singleton is statically linked/defined as part of the executable? What happens when Singleton::getInstance() is called e. g. from other (detached) threads? Could that lead to undefined behavior or will all threads (detached or not) be terminated/joined before the destructors of static variables are called?

(To be clear: I think singleton is an anti-pattern, but when I have to use it I want to know the what kind of bad things could happen.)

Aucun commentaire:

Enregistrer un commentaire