1

Is it a correct way to make singleton objects by using 2 static atomic and mutex variables to save 2 states: initializing and initialized?

For example, I only need one Application instance running in a program. Its job is to init and terminate external libraries, and prevent to create any new Application object.

#include <mutex>
#include <stdexcept>
static bool initialized;
static std::mutex mutex;
Application::Application()
{
    std::lock_guard<std::mutex> lock(mutex);

    if (initialized) throw std::runtime_error("Application::Application");

    if (!init_external_libraries())
        throw std::runtime_error("Application::Application");

    initialized = true;
}
Application::~Application()
{
    terminiate_external_libraries();
    initialized = false;
}
MiP
  • 5,846
  • 3
  • 26
  • 41
  • https://stackoverflow.com/questions/12755539/why-is-singleton-considered-an-anti-pattern – Jesper Juhl Feb 04 '18 at 14:52
  • @JesperJuhl Could you tell me how to control external libraries initialization and termination without a global singleton instance? – MiP Feb 04 '18 at 14:55
  • initialize them in `main()`? Besides, initialization of globals does *not* happen in a well-defined order except within a single translation unit. See https://isocpp.org/wiki/faq/ctors#static-init-order – Jesper Juhl Feb 04 '18 at 15:00
  • @JesperJuhl I'm making a library, so using `main` is impossible. – MiP Feb 04 '18 at 15:01
  • Avoid using multiple global variables for such petty task as such. Make constructor private or something. – seccpur Feb 04 '18 at 15:07

1 Answers1

1

Do I get it right, that init_external_libraries() has to run at most one time?

Atomics won't help you there. Operations on atomics are atomic (storing and loading values in your case), but what happens between those is not.

You could use that nice trick of having a function that has a static object and returns a reference to it. As far as I know, initialization of static values are guaranteed to happen only once.

It would look something like this:

Object &get_singleton(){
    static Object o;
    return o;
}

EDIT: And, as far as I know, this is threadsafe. Don't quote me on that though.

  • `Operations on atomics are atomic, but what happens between those is not.` Can I use a mutex lock in between? As for using `static`, a comment above said that it may have gone to a `static initialization order fiasco` pattern. – MiP Feb 04 '18 at 15:15
  • 2
    If you use a lock, you don't need atomics. Just lock, check flag, if set leave, else set flag and initialize your stuff. And unlock, of course, but you should use lock_guard [http://www.cplusplus.com/reference/mutex/lock_guard/] for that. – Peter Pannel Feb 04 '18 at 15:25
  • Regarding static: read the **How do I prevent the “static initialization order fiasco”?** part of that link. I think you do not have to worry about it if you have your static inside a function like in my example. – Peter Pannel Feb 04 '18 at 15:29