Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is Meyers' implementation of a Singleton actually a Singleton

I have been reading a lot about Singletons, when they should and shouldn't be used, and how to implement them safely. I am writing in C++11, and have come across the Meyer's lazy initialized implementation of a singleton, as seen in this question.

This implementation is:

static Singleton& instance()
{
     static Singleton s;
     return s;
}

I understand how this is thread safe from other questions here on SO, but what I don't understand is how this is actually a singleton pattern. I have implemented singletons in other languages, and these always end up something like this example from Wikipedia:

public class SingletonDemo {
        private static volatile SingletonDemo instance = null;

        private SingletonDemo() {       }

        public static SingletonDemo getInstance() {
                if (instance == null) {
                        synchronized (SingletonDemo .class){
                                if (instance == null) {
                                        instance = new SingletonDemo ();
                                }
                      }
                }
                return instance;
        }
}

When I look at this second example, it is very intuitive how this is a singleton, since the class holds a reference to one instance of itself, and only ever returns that instance. However, in the first example, I don't understand how this prevents there ever existing two instances of the object. So my questions are:

  1. How does the first implementation enforce a singleton pattern? I assume it has to do with the static keyword, but I am hoping that someone can explain to me in depth what is happening under the hood.
  2. Between these two implementation styles, is one preferable over the other? What are the pros and cons?

Thanks for any help,

like image 392
lbrendanl Avatar asked Jul 17 '13 23:07

lbrendanl


People also ask

What is Meyers singleton?

The beauty of the Meyers Singleton in C++11 is that it's automatically thread-safe. That is guaranteed by the standard: Static variables with block scope. The Meyers Singleton is a static variable with block scope, so we are done. It's still left to rewrite the program for four threads.

What is one of the most common mistakes you can make when implementing a singleton?

A common mistake with that implementation is to neglect synchronization, which can lead to multiple instances of the singleton class.

What is singleton when you will use singleton?

Singleton pattern restricts the instantiation of a class and ensures that only one instance of the class exists in the java virtual machine. The singleton class must provide a global access point to get the instance of the class.

What are the disadvantages of applying GOF Singleton pattern?

They violate the single responsibility principle: by virtue of the fact that they control their own creation and lifecycle. They inherently cause code to be tightly coupled. This makes faking them out under test rather difficult in many cases. They carry state around for the lifetime of the application.

What is Meyers' Singleton?

:) This implementation is known as Meyers' Singleton. Scott Meyers says: "This approach is founded on C++'s guarantee that local static objects are initialized when the object's definition is first encountered during a call to that function." ...

Is Meyer's Singleton the preferred method for static initialization?

So once that section of standard is widely implemented, Meyer's Singleton will be the preferred implementation. I disagree with many answers already. Most compilers already implement static initialization this way. The one notable exception is Microsoft Visual Studio. Show activity on this post.

What is singleton design pattern?

Singleton Design Pattern | Introduction The singleton pattern is one of the simplest design patterns. Sometimes we need to have only one instance of our class for example a single DB connection shared by multiple objects as creating a separate DB connection for every object may be costly.

What is a singleton class in Java?

The singleton pattern is a design pattern that restricts the instantiation of a class to one object. Let’s see various design options for implementing such a class. If you have a good handle on static class variables and access modifiers this should not be a difficult task. Method 1: Classic Implementation


2 Answers

This is a singleton because static storage duration for a function local means that only one instance of that local exists in the program.

Under the hood, this can very roughly be considered to be equivalent to the following C++98 (and might even be implemented vaguely like this by a compiler):

static bool __guard = false;
static char __storage[sizeof(Singleton)]; // also align it

Singleton& Instance() {
  if (!__guard ) {
    __guard = true;
    new (__storage) Singleton();
  }
  return *reinterpret_cast<Singleton*>(__storage);
}

// called automatically when the process exits
void __destruct() {
  if (__guard)
    reinterpret_cast<Singleton*>(__storage)->~Singleton();
}

The thread safety bits make it get a bit more complicated, but it's essentially the same thing.

Looking at an actual implementation for C++11, there is a guard variable for each static (like the boolean above), which is also used for barriers and threads. Look at Clang's AMD64 output for:

Singleton& instance() {
   static Singleton instance;
   return instance;
}

The AMD64 assembly for instance from Ubuntu's Clang 3.0 on AMD64 at -O1 (courtesy of http://gcc.godbolt.org/ is:

instance():                           # @instance()
  pushq %rbp
  movq  %rsp, %rbp
  movb  guard variable for instance()::instance(%rip), %al
  testb %al, %al
  jne   .LBB0_3
  movl  guard variable for instance()::instance, %edi
  callq __cxa_guard_acquire
  testl %eax, %eax
  je    .LBB0_3
  movl  instance()::instance, %edi
  callq Singleton::Singleton()
  movl  guard variable for instance()::instance, %edi
  callq __cxa_guard_release
.LBB0_3:
  movl  instance()::instance, %eax
  popq  %rbp
  ret

You can see that it references a global guard to see if initialization is required, uses __cxa_guard_acquire, tests the initialization again, and so on. Exactly in almost every way like version you posted from Wikipedia, except using AMD64 assembly and the symbols/layout specified in the Itanium ABI.

Note that if you run that test you should give Singleton a non-trivial constructor so it's not a POD, otherwise the optimizer will realize that there's no point to doing all that guard/locking work.

like image 97
Sean Middleditch Avatar answered Oct 16 '22 16:10

Sean Middleditch


// Singleton.hpp
class Singleton {
public:
    static Singleton& Instance() {
        static Singleton S;
        return S;
    }

private:
    Singleton();
    ~Singleton();
};

This implementation is known as Meyers' Singleton. Scott Meyers says:

"This approach is founded on C++'s guarantee that local static objects are initialized when the object's definition is first encountered during a call to that function." ... "As a bonus, if you never call a function emulating a non-local static object, you never incur the cost of constructing and destructing the object."

When you call Singleton& s=Singleton::Instance() first time the object is created and every next call to Singleton::Instance() results with the same object being returned. Main issue:

  • subject to Destruction Order Fiasco (the equivalent to the Initialization Order Fiasco)

Another implementation is called the trusty leaky Singleton.

class Singleton {
public:
    static Singleton& Instance() {
        if (I == nullptr) { I = new Singleton(); }
        return *I;
    }

private:
    Singleton();
    ~Singleton();

    static Singleton* I;
};

// Singleton.cpp
Singleton* Singleton::I = 0;

Two issues:

  • leaks, unless you implement a Release and make sure to call it (once)
  • not thread safe
like image 35
4pie0 Avatar answered Oct 16 '22 17:10

4pie0