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.
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))).
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'.
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.
"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.
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.
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.
"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).
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.
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.
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.
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.
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.
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.
> A global variable is more useful than singleton, since it comes with no battery, plan or pretense.
Initialization and deinitialization of globals in C++ is a trainwreck. A singleton wrapper like the one I proposed upthread gives you deterministic initialization order and doesn't impose a runtime performance penalty.
> Singleton at minimal requires thread-safety
Both Windows and POSIX have locks that can be statically initialized. In Windows,
Now you can serialize access to your singleton without having to do any explicit and delicate lock initialization. Of course, this isn't the only approach --- you can make the singleton itself threadsafe and have your generic singleton wrapper serialize initialization using a similar approach. TIMTOWTDI.
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.
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.
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)
I understand your point of view, but that kind of problem is application specific. When we have to deal with these constraints, of course the use of a Singleton is dumb.
If I had to deal with these, I'll change my implementation to fit to my needs. That's all.
Maybe the term "generic" was too heavy for the use cases I described.
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.
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.)
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.