3 ms·
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 g
by enki42 14y ago
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 14y agoA 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 14y agoWhy 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 14y agoWhat 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 14y agoThe 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)
- enki42 14y agoI 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.
- quotemstr 14y ago> 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, SRWLOCK g_thing_lock = SRWLOCK_INIT; With pthreads, pthread_mutex_t g_thing_lock = PTHREAD_MUTEX_INITIALIZER; 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.