

C++11: A generic singleton - vjeux
http://enki-tech.blogspot.fr/2012/08/c11-generic-singleton.html

======
quotemstr
No no no no no. This approach still needs heap allocation, and you still need
to chase a pointer for every access to your singleton. That's silly. There's a
much better way. Here it is, roughly speaking.

    
    
      template<typename T>
      struct singleton_bss {
          T& get() {
              return * ((T*) &this->buffer[0]);
          }
      
          void init(T&& value) {
              new ( (T*) &this->buffer[0] ) T(std::forward<T>  (value));
          }
        
          union {
              char buffer[sizeof(T)];
              long align; // adjust to taste
          };
      };
    
      singleton_bss<mything> g_thing;
    

This approach has the huge advantage of not doing any heap allocation. The
storage for g_thing lives directly in bss, the portion of your processes'
address space initialized by the operating system. g_thing.init() cannot fail
if T's constructor is non-throwing --- singleton_bss allocates no memory!

Access to g_thing is much more efficient than access to a typical singleton.
There's no pointer-to-the-instance stored in the singleton, so there's no
pointer chasing. Access to g_thing is exactly as efficient as access to a
plain global variable, which is as efficient as variable access can be.

You can trivially construct a version of singleton_bss that does lazy
initialization, takes multiple parameters, destroys the object on module
unload, and so on.

~~~
keveman
Here is the C++11 way of specifying alignment :

    
    
        alignas(T) char buffer[sizeof(T)];

Or better still, just use the unrestricted union feature :

    
    
        union {
          T t;
        };

Just use &t in place of buffer.

~~~
quotemstr
Thanks for the tip --- alignas slipped my mind. The compiler I use for most of
my work doesn't yet support alignas (or unrestricted unions). I believe a
VC++-specific equivalent would for the former trick would be
__declspec(align(__alignof(T))).

~~~
keveman
Yeah, you are right, alignas is still unsupported in many compilers. clang 3.2
supports it. However, unrestricted unions has been supported in many compilers
for a long time now. I would use that in this case, since you already know the
type 'T'.

------
skrebbel
Hooray, now you can use anti-patterns in a _generic_ way!

I have yet to find a single good reason for having singletons, other than
dealing with legacy code that has them (and, potentially, logging). Singletons
are the worst anti-pattern out there, removing any sense of testability and
reconfiguration in your project.

The only good-ish argument for singletons (other than, again, dealing with
legacy code that has them) is that inversion of control requires so many
objects to be passed around to constructors. This argument becomes invalid
once you realise that many-instances-needed-on-constructors is in fact a
warning sign that your classes are getting too tightly bound. Draw out the
entities again and see where you can abstract or generalize.

~~~
pmelendez
"I have yet to find a single good reason for having singletons, other than
dealing with legacy code that has them (and, potentially, logging). Singletons
are the worst anti-pattern out there, removing any sense of testability and
reconfiguration in your project"

I think you are being a bit dogmatic here. There are good uses for singleton
classes in single threaded applications that don't use unit tests (i.e most
mobile games). People should just think and evaluate each case instead or
tagging stuff as pattern or anti-pattern. Am I the only one who think that
both (pattern and anti-pattern) are evil? This reminds me a lot all the goto
controversy.

~~~
malkia
By this logic anything is acceptable.

~~~
pmelendez
If there is a good use for it... Why not? In medicine stuff that normally hurt
you is used to cure you as well... You just need to know when and how to use
it.

~~~
malkia
There is no good use for singletons.

    
    
      void callback_from_read(int err)
      {
      #if USE_SINGLETON
         if( err < 0 )
             log::instance()::printf("blah... err=%d", err);
      #else
         if( err < 0 )
             theLog->printf("blah... err=%d", err);
      #endif
      }
    
      ...
    
      do_read( something, somesize, callback_from_read );
    
      ...
    

Now thing about it. If this read came from the I/O in some thread with limited
stack, it would've wanted to initialize theLog::instance():: the first time it
calls it. That function itself might want to read a file, but the underlying
system does not allow a file to be reopened while it's still in the I/O
callback. Even if it does, there might not be enough place on the stack, or it
could be called from a thread where the stuff you are trying to do is not
going to work.

Ah, and you would have to make it thread safe at this point (if the callback
is in a thread), since someone might've called log::instance()::printf() from
the main-thread.

Other things might happen if more locks are involved, and different thread
priorities like priority inversion.

The problem is that log::instance()::printf() might do two things -
INIT_LOG(), and DO_LOG() - the singleton pattern combines them into ONE, where
it should've kept them separate. You might be able to reason about DO_LOG
anywhere in the code, but combined with INIT_LOG becomes very hard, and even
impossible.

As such singletons are introducing coupling, and reduce severely the reasoning
about what the code might do.

~~~
pmelendez
I thought I was very specific...

"There are good uses for singleton classes in _single threaded applications_
that _don't use unit tests_ "

In any case I didn't say that logging was the only use. In gaming, we had used
it a lot when sharing single resources across all the game such a config file.
And if you can take a peak to Unreal Engine you would see how those guys abuse
of them without too many problem.

I do not want to be an advocate of using Singletons. I am aware of the risks
and problems it brings with. But sometimes people forget that not every
application is multithreaded nor implement unit tests.

My fear with that is when people forget why it was bad on first place (just
like it happened with the goto keyword).

------
shanemhansen
I have a lot of respect for those C++ guys/girls.

Frankly, If I had to think this hard to get my code written, I wouldn't be
writing very much of it. Thank heavens for small languages that leave my brain
cycles to think about solving other problems.

But don't listen to me, listen to Linus and Rob Pike.

[http://commandcenter.blogspot.com/2012/06/less-is-
exponentia...](http://commandcenter.blogspot.com/2012/06/less-is-
exponentially-more.html)

<http://harmful.cat-v.org/software/c++/linus>

~~~
stephen_g
Do you mean a small language such as C? Because I disagree completely.

Whenever I use C, I always seem to find myself wishing for C++'s string class,
the STL containers and exception handling... There are libraries for C to get
containers and things but C interfaces tend to be uglier (in my opinion) and
it's annoying to have to use a lot of 3rd party stuff to get things that come
with C++.

Just because C++ has a ton of other features (many of which are pretty easy to
use incorrectly if you don't know how) doesn't mean you have to use all of
them.

~~~
shanemhansen
C is small and beautiful, but my preference is more along the lines of go, or
maybe objective-c or d.

------
02f39nrca
Experience shows the singleton pattern is more trouble than it's worth.
Explicitly initialise shared resources in one thread either from main, or if
you're writing a shared library, the explicit initialisation function you'll
have to add anyway if the library is properly designed.

------
btilly
This is interesting.

But be aware that singletons are to be regarded cautiously for all of the
reasons that, say, global variables are.

~~~
klodolph
Plus some additional reasons: if a singleton is initialized on first use, it
might be hard to reason about which kind of environment exists when it is
initialized -- what locks are held, etc.

------
enki42
Hi everyone! I'm the author of this blog.

I agree with most of you that Singleton can lead to destroy a design. I just
think that we should not ban something globally, and I'm sure that this
(anti-?)pattern can be useful sometimes.

The aim of this post was not to encourage people to use Singleton, but to show
how C++11 can improve our way to write classical code. I just took a simple
example of singleton.

~~~
malkia
A global variable is more useful than singleton, since it comes with no
battery, plan or pretense.

Singleton at minimal requires thread-safety, and that comes very hard. It also
contradicts with itself when a singleton is made thread-specific variable
(TLS) - because it's singleton / thread, but not per process.

~~~
enki42
Why should a Singleton be thread safe? Nothing says that it will be used in a
multi-threaded environment... For me a Singleton must fulfill the
specification given by the Gang of Four.

I'm not saying that it should not be thought thread safe, I just say that it's
not the point here.

~~~
malkia
What is better then:

g_current_context->Something() or g_current_context::singleton()->Something()

Because I can set in a special place g_current_context to the initial value
knowing it would be safe to do so, while the singleton is going to set it,
once it's first needed, and that might not be appropriate.

The problem with singleton's is that initialization is not controlled - what
if the singleton is for the first time called from function that already ate
too much stack, and now the initialization routine for the singleton wants
more?

What if it was called from thread? Or interrupt routine? Or during time
sensitive operation that needs to finish on-time (like something producing
audio samples, which called every 5ms, need to finish in 2-3ms).

Or callback that needs to return as soon as possible to the caller.

How are you going to deal with it then?

It's much better to be explicit in this case, have a safe place, where no
threads are created yet and initialize it, without any protection needed, and
then use it as global variable.

Even better, if possible, put all these variables in page (if the OS allows) -
initialize them, and then make them READONLY - to know that's not going to
change.

~~~
pmelendez
The only thing is that is not always easy to maintain an unique
g_current_context across all your classes, specially if you have cross
references between your headers. In those cases it is handy to have
Sing::I().something() instead of local_pointer_to_context->something(), where
you have to maintain several instances of the same context.

Again, singleton are known to do not be thread-safe so I am just talking about
single thread apps (which still exists)

------
zerohp
I prefer the answer given here:

[http://stackoverflow.com/questions/1463707/c-singleton-vs-
gl...](http://stackoverflow.com/questions/1463707/c-singleton-vs-global-
static-object)

~~~
pfedor
This is wrong for reasons given here: [http://google-
styleguide.googlecode.com/svn/trunk/cppguide.x...](http://google-
styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables)

~~~
pmelendez
I am not sure if that applies here... Static objects introduce hard to find
bugs because you can't figure out the order of instantiation... Over here
there is just one unique instance so you know exactly where it was
instantiated.

~~~
pfedor
But that unique instance is presumably referenced by other objects which may
want to use it as part of their own shut down logic, at which point it might
no longer exist. (And things get only worse in the presence of threads.)

~~~
pmelendez
Sorry I read it again (the first time I was reading it on my phone) and I
thought we were discussing about Meyers singleton:

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

Which in the proper context is perfectly fine.

This is wrong:

class myclass { // can have state // ... public static myclass m = new
myclass(); // globally accessible static instance, which can have state }

and the first link itself explain why.

------
vjeux
Nice use of perfect forwarding!

------
vadeo
Cool article

------
RomP
one word: synchronization

