c++ Play it only once Sam

Just how many times you have admitted to yourself it was rather foolish to think of globals in C++ as “a simple thing” 🙂 After all: What could possibly go wrong? If you know what I am talking about please proceed.

As it turns out many things can and will go wrong, with what you think of as C++ global variables and functions. I am sure every now and then, you are wondering why is this singleton not a singleton, why is this function called more than once,  and how it is, that nobody seems to care?

After many years of various coding idioms, that handle static linkage and global variables, and the famous “Singleton Pattern” implementations, may I be so bold to remind you: you do not have to dance around these issues any more.

It is 2018 after all.

As from C++11 you have new memory model to enjoy and from C++17 you have inline variables.

And since C++ primordial soup you have local statics. Aka static local variables.  And as if this would be an end to this list of crucial C++ ingredients,  there is one more: lambdas.

And do not forget the big gotcha: Internal linkage and anonymous namespace’s.

So you are thinking now: What is this? The whole of standard C++17? Is that it?

Well no my dear readers, no. Humble myself has prepared one delicious little nugget for you to readily copy paste into your code:

Please observe carefully the above:

  • the big gotcha: anonymous namespace implies default static linkage for variables inside. Thus do not put this code inside it. This is header code. This dbj_once namespace deliberately has a name.
    If this would be anon. namespace variables inside will be treated as if they are static. Which will make things to be called as many times as you have compilation units. Aka “cpp files”.
    Effectively inline singleton & instance(), will be linked as: static singleton & instance(). Please make sure to devote some time to the  “Internal linkage” and anon. namespace’s subject.
  • Lock Free. Since C++11, this is safe in presence of multiple threads (MT) and is supported as a such by all major compilers. No std::mutex or some other kind of locking is necessary.
  • Call Once Mechanism. Inside instance() , is an anonymous lambda which is guaranteed to be called only once.
  • This coding idiom is safe to use in header only situations. Very important for modern and standard C++.

Please do remember: until C++11 to achieve the same this was much more involved. Much more.

Now (one might ask) why not just using std::call_once ?  Or if you are WIN32 afficionado, why no just use InitOnceExecuteOnce() function?  These two btw.  are clearly illustrating what do I mean by “it was much more involved”, in them bad old days before C++11.

You can, but you do not have too use the legacy singleton idioms. It is as simple as that. Code presented here is standard C++ and does it all, for you.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.