почему MSVC Потокобезопасная инициализация статических локальных переменных использует TLS - PullRequest
0 голосов
/ 05 июня 2019

Выше VS2015, с / Zc: threadSafeInit, инициализация статического локального varibal является поточно-ориентированной, но MSDN сказал

Потоково-безопасные статические локальные переменные используют внутреннее хранилище потоков (TLS) для обеспечения эффективного выполнения, когда статический объект уже инициализирован.

xp игнорирует сегмент .tls, если динамическая загрузка dll с LoadLibrary

так

  1. зачем использовать tls и как это работает efficient?
  2. использует ли std :: call_once tls?
  3. как реализовать thread-safe-init без tls?

Ссылка цитаты находится здесь Потоковая безопасная локальная статическая инициализация

Реализация этой функции зависит от функций поддержки операционной системы Windows в Windows Vista и более поздних операционных системах. Windows XP, Windows Server 2003 и более старые операционные системы не имеют такой поддержки, поэтому они не получают преимущества в эффективности.

мой тестовый код:

class AA
{
public:
    int m_a = 1;
};

AA* getAA()
{
    static AA a;
    return &a;
}

int main()
{
    AA* pa = getAA();
    return 0;
}

с /Zc:threadSafeInit, функция getAA в разборке:

008c1000 55              push    ebp
008c1001 8bec            mov     ebp,esp
008c1003 64a12c000000    mov     eax,dword ptr fs:[0000002Ch]
008c1009 8b08            mov     ecx,dword ptr [eax]
008c100b 8b15b8338c00    mov     edx,dword ptr [testStatic!__favor+0x4 (008c33b8)]
008c1011 3b9104000000    cmp     edx,dword ptr [ecx+4]
008c1017 7e2d            jle     testStatic!getAA+0x46 (008c1046)
008c1019 68b8338c00      push    offset testStatic!__favor+0x4 (008c33b8)
008c101e e809020000      call    testStatic!_Init_thread_header (008c122c)
008c1023 83c404          add     esp,4
008c1026 833db8338c00ff  cmp     dword ptr [testStatic!__favor+0x4 (008c33b8)],0FFFFFFFFh
008c102d 7517            jne     testStatic!getAA+0x46 (008c1046)
008c102f b9bc338c00      mov     ecx,offset testStatic!a (008c33bc)
008c1034 e817000000      call    testStatic!AA::AA (008c1050)
008c1039 68b8338c00      push    offset testStatic!__favor+0x4 (008c33b8)
008c103e e89f010000      call    testStatic!_Init_thread_footer (008c11e2)
008c1043 83c404          add     esp,4
008c1046 b8bc338c00      mov     eax,offset testStatic!a (008c33bc)
008c104b 5d              pop     ebp
008c104c c3              ret

и /Zc:threadSafeInit- (закрыть функцию), функция getAA в разборке:

010e1000 55              push    ebp
010e1001 8bec            mov     ebp,esp
010e1003 a180330e01      mov     eax,dword ptr [testStatic!a+0x4 (010e3380)]
010e1008 83e001          and     eax,1
010e100b 7519            jne     testStatic!getAA+0x26 (010e1026)
010e100d 8b0d80330e01    mov     ecx,dword ptr [testStatic!a+0x4 (010e3380)]
010e1013 83c901          or      ecx,1
010e1016 890d80330e01    mov     dword ptr [testStatic!a+0x4 (010e3380)],ecx
010e101c b97c330e01      mov     ecx,offset testStatic!a (010e337c)
010e1021 e80a000000      call    testStatic!AA::AA (010e1030)
010e1026 b87c330e01      mov     eax,offset testStatic!a (010e337c)
010e102b 5d              pop     ebp
010e102c c3              ret
...