featherless biped
featherless biped

Reputation: 173

C++ Multithreading - Thread safe code

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

Answers (1)

SergeyA
SergeyA

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

Related Questions