2

I am implementing something very similar to the question here.

Window::Window() { static bool flagInit = true; if (flagInit) { doInit(); // doInit should be called only once. flagInit = false; } createWindow() } 

I understand that using static variables can generally be a bad idea when it comes to multithreading. If two threads create Window instance at the same time, flagInit might fail to work due to data race. But Singleton class won't do me the job either, since I want to create multiple instance of the class.

Window toolTip, mainWindow; 

If I add a mutex to the initialization part, does that make it thread safe? Also, is that a good pratice to do so?

Window::Window() { { std::scoped_lock<std::mutex> lock(mutex); static bool flagInit = true; if (flagInit) { doInit(); // doInit should be called only once. flagInit = false; } } createWindow() } 

PS doInit() comes from someone else's library so I cannot do anything to it

1
  • Re, "static variables can...be a bad idea when it comes to multithreading." Not only in multi-threaded programs. Static variables also are a hinderance to testing and, to re-useability. I personally use static variables only when I am forced to do so (e.g., in an embedded system where I am prohibited from using the heap) or, in projects so small and so short-lived that I would not be sad if I lost the source code. Commented Jun 11, 2020 at 12:58

1 Answer 1

4

There's a tool exactly for this: std::call_once:

class Window { static std::once_flag flagInit; // ... }; Window::Window() { std::call_once(flagInit, doInit); // Note: can throw createWindow(); } 

You can also technically still accomplish this with statics since C++11 made their initialization thread-safe:

Window::Window() { static bool flagInit = (doInit(), false); createWindow() } 
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your kind help! Both ways seem very elegant to me. For static bool flagInit = doInit(), false; I am not familiar with the grammar here. Could you throw me a link maybe?
@charliepu123, It's using the comma operator. You need some kind of value there because it's initialization, but doInit could return void, so this ensures there's some value. The type and actual value don't matter since you'll never need to use that variable after. With that said, in C++17, I'd personally go for [[maybe_unused]] static bool _ = doInit(), false; or something similar since it puts aside the name and makes it clear the variable is deliberate.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.