1. Pointer must be atomic
2. Check, lock, check, construct
std::atomic<Foo*> foo { nullptr };
Foo* instance()
{
Foo* f = foo; // single load of foo
if (!f)
{
std::lock_guard<std::mutex> l(foo_lock);
if (!foo)
{
foo = f = new Foo(); // assign both foo and f
}
}
return f;
}
Even better, use std::unique_ptr and std::once to get automatic cleanup and less scaffolding
class Foo
{
public:
static Foo& instance()
{
std::call_once(_create, [=]{
_instance = std::make_unique<Foo>();
});
return *_instance;
}
private:
static std::unique_ptr<Foo> _instance;
static std::once_flag _create;
};
Or just use a function local static
Foo& Foo::instance()
{
static Foo foo;
return foo;
}