I want to find out whether 2 calls to Get()
with different parameter types in the code below are thread-safe:
struct MethodTypeIndex
{
template <typename T>
static size_t Get(T)
{
static size_t index = NextIndex();
return index;
}
private:
static size_t NextIndex()
{
static size_t nextIndex = 0;
return nextIndex++;
}
};
On the one hand, NextIndex()
is called during the initialization of index
and according to standard:
§6.7 [stmt.dcl] p4
If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.
On the other hand, I don't know if call to NextIndex()
is considered as part of initialization of index
. And if not, does brace-initialization make difference?
static size_t index{ NextIndex() };
Or is there any other ways to make it thread safe, if I don't want to make nextIndex
atomic?
Starting in C++11, scoped static initialization is now thread-safe, but it comes with a cost: Reentrancy now invokes undefined behavior.] The rule for static variables at block scope (as opposed to static variables with global scope) is that they are initialized the first time execution reaches their declaration.
Static variables are not thread safe. Instance variables do not require thread synchronization unless shared among threads. But, static variables are always shared by all the threads in the process. Hence, access to static variable is not thread safe.
Pretend for a moment that you have two different functions:
static size_t get_int() {
static size_t index = NextIndex();
return index;
}
static size_t get_long() {
static size_t index = NextIndex();
return index;
}
Is there any doubt in your mind that calling these two functions from separate threads is not thread-safe? Clearly there’s a data race in the calls to NextIndex
.
Creating those functions by instantiating a template function doesn’t get rid of the data race. Templates are not code; they are patterns for creating code. Calling two different instantiations of your template function (for example, Get<int>()
and Get<long>()
) from two different threads produces a data race.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With