2

To clarify, I'm not talking about multi-threaded environment. I often come across a situation where I have to allocate some resources in an init function (and consequently release the resource in a terminate function) and where I would like to avoid calling it twice. I was wondering if there was something like a built-in keyword in C/C++ to make it callable once. Something more sophisticated than a static local variable that I would have duplicated across all my init functions like

static bool isInitialized = false; 
if (!isInitialized) {
  isInitialized =   true;
//...
} 

Or maybe it isn't that bad and I could hide this behind a macro CALLABLE_ONCE.

I'm open to any solutions from C/C++03/C++11/C++14.

EDIT:

The reason why I would be using the init/terminate scheme on the global scope would mainly be due to the fact that I tend to create namespaces for entities that shouldn't be instantiated more than once and avoid using singleton as encouraged on this post. Of course using a class would be easier as I would simply use the constructor/destructor, but how can one initialize (only once) this kind of entities(namespaces)?

Community
  • 1
  • 1
pandaman1234
  • 523
  • 7
  • 17
  • 2
    Is there something preventing you from doing this inside the constructor/destructor ? – Telokis Feb 18 '17 at 18:01
  • 1
    I don't know of any facility in C++, that exposes this functionality. On Windows, you can take advantage of the [One-Time Initialization](https://msdn.microsoft.com/en-us/library/ms686934.aspx) facilities. – IInspectable Feb 18 '17 at 18:05
  • @Ninetainedo Yes, I'm looking for something that works in a global function/static member function. If I would use a constructor/destructor, that would basically mean having to use a singleton of some sort. I could have a member flag that says if I'm initialized in all cases, but I was looking for a keyword, or a hack by passing a lambda to a function. – pandaman1234 Feb 18 '17 at 18:05
  • 1
    Well... singletons implemented using magic statics don't require you to manually keep a flag about the initialization state around. – IInspectable Feb 18 '17 at 18:06
  • 1
    You are not supposed to have functions such as `init`, that's what constructors are for. Maybe you should take a look at [scope guards](https://stackoverflow.com/questions/10270328/the-simplest-and-neatest-c11-scopeguard#10270809). – nwp Feb 18 '17 at 18:06
  • 1
    *"Something more sophisticated than a static local variable"* - The "call once" is a property of each individual function. A static local variable is also just that. Why over-complicate when you have a simple idiom already? There isn't a portable way to do this with less typing. – StoryTeller - Unslander Monica Feb 18 '17 at 18:29
  • Embrace [Resource Allocation Is Initialization](http://stackoverflow.com/questions/2321511/what-is-meant-by-resource-acquisition-is-initialization-raii) – user4581301 Feb 18 '17 at 18:42

1 Answers1

2

There is std::call_once, although presented to be used with threads rather than just one thread application, it can be used by a one thread application too.

The one problem you may encounter is if it throws, then it is not considered initialized. You may protect the initialization function with a try/catch if required, though.

Also in your case you may want a public static function and another function that is private. The public static function would perform the std::call_once. Something like this:

class my_class
{
public:
  static void init()
  {
     std::call_once(m_initialized, private_init);
  }

private:
  static void private_init()
  {
     ... // init here
  }

  static std::once_flag   m_initialized;
};

As you can see, it looks exactly the same as your function, except that the if() and flag switch are hidden. You could also keep the m_initialized flag in your first function as a static variable.

The one difference, though, is that the std::call_once is thread safe.

Community
  • 1
  • 1
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
  • +1 and thanks for the highlight on std::call_once that can be used on a one thread app. It could also very well be used in my case. But is the static local variable initialization in my case also thread safe as explained [here](http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11)? I'll post an edit which will hopefully explain why I'm looking for global functions compatible solutions such as this one. – pandaman1234 Feb 19 '17 at 05:03
  • @lordjohncena, the static variable itself will be initialized in a safe manner since C++11 (they know whether you created threads, so it is really fast if you have a one thread app.) However, your `if()` and `var = true` would need a mutex... The `std::call_once()` takes care of that for you if you use it. – Alexis Wilke Feb 19 '17 at 21:29