Reputation: 173
I'm working on a game engine that runs from a .dll. Inside, there is an exported function that returns a reference to a static class declared in it, like below:
__forceinline __declspec(dllexport) STATE* NF3DGetEngineState(void)
{
static STATE s_State;
return &s_State;
}
where STATE
is a class that manages all components and has functions that accesses them via a critical section:
void Set(int val)
{
EnterCriticalSection(&CriticalSection);
ClassMember = val;
LeaveCriticalSection(&CriticalSection);
}
where "CriticalSection" is a CRITICAL_SECTION
member of the STATE
class that is of course initialised. The context in which I use these functions is:
NF3DGetEngineState()->Set(10);
The question is: is this code thread safe?
From what I learnt, returning references to static declarations is not thread safe.
What can I do to make it so?
Upvotes: 2
Views: 314
Reputation: 62613
Which is your C++ version? If it is C++11 or later, than the code is as thread safe as it gets. If it is pre-11, it is unsafe with regards to first call to NF3DGetEngineState
.
Clarification.
It is not that returning references to static variables 'is not thread safe'. On the contrary, it is 100% safe. What is not thread-safe pre-C++11 is static variable initialization itself. pre-C++11 makes no guarantees in regards to the concurrent calls to the function for the first time. In fact, all pre-11 C++ compilers I worked with would have a problem if you concurrently enter this function for the first time. The reason is, the code which compiler generates when static variables are used, looks approximately like following:
static bool static_var_initialized = false;
if (!static_var_initialized) {
new (&static_var) StaticVarType(); // Explicit constructor call
static_var_initialized = true;
}
Obviously, there is a possibility of calling constructor multiple times if you happen to call this function multiple times before static variable is set to true.
In C++11, there is a guarantee that it will never happen, and constructor will be called only once. It also guarantees no threads will see unconstructed value.
Upvotes: 4