C 11 mandates that static variables inside a function are atomically initialized for the first run of the function. The only way to do that efficiently is double-checked locking to prevent an expensive mutex-lock all the time.
I just had the necessity to have an static atomic<size_t> inside a function. It wouldn't make sense if such an atomic would be atomically initialized through double-checked locking. Instead it should be handled like another static initialized non-const native variable.
I checked the generated code with VC and Intel C under Windows and clang and g under Linux and all generated code according to my expectations. But is this really reliable and mandated by the standard that atomics should be handled independent of other objects here ?
CodePudding user response:
The default constructor of std::atomic
is constexpr, although until C 20 that's because it's trivial and the object can't yet be used. That means that no dynamic initialization is required, which is as close as the standard gets to saying that this is efficient.
CodePudding user response:
Davis Herring is mostly right, it's because the datatype is a trivial datatype and the compiler can inspect its initialization to not have any side-effects (constexpr construction actually isn't necessary). I checked that with the following code:
#include <iostream>
using namespace std;
struct S
{
S( int i ) : i( i ) {}
operator int() { return i; }
~S() {}
private:
int i;
};
S &f();
int main()
{
cout << f() << endl;
}
#if defined(_MSC_VER)
__declspec(noinline)
#elif defined(__llvm__) || defined(__GNUC__)
__attribute((noinline))
#endif
S &f()
{
static S s( 123 );
return s;
}
The above code generates the usual double-checked locking initialization. If you comment out the destructor of S the code in f() just returns a reference to statically initialized data in modifiable memory.