but i use tens of itis isinitialised flags in every program and i got no slowdovn in case of them.. does c++ standard just mean that if i just use any static variable it would guard it all with locks? hell no, i hope
C++11 changed the required behavior here. Some compilers support much of C++11 but not this feature. Other compilers have compile options to turn it off.
Instead of guessing what the compiler is doing, _look at the assembly output_. I can't stress this enough. Real engineers delve into how the boxes they build off of are constructed.
Consider:
#include <stdlib.h>
int foo() {
static int bar = rand();
}
On GCC 4.9 with full optimizations, this produces:
foo():
cmp BYTE PTR guard variable for foo()::bar[rip], 0
je .L2
mov eax, DWORD PTR foo()::bar[rip]
ret
.L2:
sub rsp, 24
mov edi, OFFSET FLAT:guard variable for foo()::bar
call __cxa_guard_acquire
test eax, eax
jne .L4
mov eax, DWORD PTR foo()::bar[rip]
add rsp, 24
ret
.L4:
call rand
mov edi, OFFSET FLAT:guard variable for foo()::bar
mov DWORD PTR [rsp+12], eax
mov DWORD PTR foo()::bar[rip], eax
call __cxa_guard_release
mov eax, DWORD PTR [rsp+12]
add rsp, 24
ret
It won't take a lock every single time, but it does check a global boolean. The gist is something like:
if not initialized
lock
if not initialized
set initial value
initialied = true
end if
unlock
end if
C++11 only requires that function-scope static initialization is thread-safe, so different compilers or different runtimes may implement this less efficiently.
Note that this only applies to initialization of function-local static variables (to non-zero values). The following bit of code can have the lock optimized away with no non-standard effects:
#include <stdlib.h>
bool foo() {
static bool bar = false;
if (!bar)
bar = rand() == 0;
return bar;
}
Compiles to:
foo():
movzx eax, BYTE PTR foo()::bar[rip]
test al, al
je .L7
ret
.L7:
sub rsp, 8
call rand
test eax, eax
sete al
mov BYTE PTR foo()::bar[rip], al
add rsp, 8
ret