Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
а зачем используется InterlockedCompareExchangeRelease вместо InterlockedCompareExchange?
Записьbв память необходимо оформить как операцию Release; тогда все предыдущие операции вынуждены отразиться в памяти до того, как другие процессоры увидят новое значениеb.
class Something
{
int v;
public:
Something() throw();
int f();
};
int f()
{
static Something s;
return s.f();
}
/* Emit code to perform this initialization but once. This code
looks like:
static guard;
if (!guard.first_byte) {
if (__cxa_guard_acquire (&guard)) {
bool flag = false;
try {
// Do initialization.
flag = true; __cxa_guard_release (&guard);
// Register variable for destruction at end of program.
} catch {
if (!flag) __cxa_guard_abort (&guard);
}
}
превращающийся в такой ассемблерный исходник:
f():
.LFB0:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl guard variable for f()::s, %eax
movzbl (%rax), %eax
testb %al, %al
jne .L2
movl guard variable for f()::s, %edi
call __cxa_guard_acquire
testl %eax, %eax
setne %al
testb %al, %al
je .L2
movl f()::s, %edi
call Something::Something()
movl guard variable for f()::s, %edi
call __cxa_guard_release
.L2:
movl f()::s, %edi
call Something::f()
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
А __cxa_guard_acquire/__cxa_guard_release в правильно сконфигурированном libstdc++ использует мьютексы (libstdc++-v3/libsupc++/guard.cc).calculate_nominal-функции были чистыми. А если они чистые, то вообще какой смысл в lazy-инициализации? Посчитать заранее константы, и наступит счастье, в том числе и по эффективности.
Потоко-безопасная ленивая инициализация в C++