2

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?

5
  • 2
    Please explain why you think it's not thread safe Commented Oct 23, 2015 at 12:20
  • I heard that returning references to static declarations is not thread safe? Am I right? Commented Oct 23, 2015 at 12:21
  • What are you doing with ClassMember? You need to use the same ressource protection while setting. Commented Oct 23, 2015 at 12:21
  • I return it in other get-type functions that contain, in quite the same manner, a critical section lock-release mechanism. The difference is that EnterCriticalSection and LeaveCriticalSection are called in the constructor and destructor of a wrapper class that is always declared in that function. Commented Oct 23, 2015 at 12:25
  • 1
    The first call to NF3DGetEngineState() may not be thread-safe, depending on the compiler. But if you call it once in the main startup (before multiple threads try to access it), after that parallel calls will get the same instance. Commented Oct 23, 2015 at 12:42

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This is what I was looking for. Thank you for your much needed help! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.