Сообщение thread_local in C++17 от 01.02.2023 8:53
Изменено 01.02.2023 9:17 Videoman
thread_local in C++17
Код вычистить пока не удалось, так что попробую пока своими словами. Появилась следующая проблема с thread_local объектом:
Если некий std::map, который объявлен как static в одном из С++ файлов. Также есть thread_local объект — регистратор, который всё что делает, в своём конструкторе регистрирует себя в static std::map, а в деструкторе разрегистрирует. Схема примерно такая:
В msvc- компилирует всё как задумано, вызывает конструкторы/деструкторы thread_local объекта в каждом потоке.
g++ и clang — вызывают конструктор/деструктор thread_local регистратора только для основного потока с main, во всех остальных потоках тишина.
У меня есть только одна догадка, что так как служебные потоки не обращаются непосредственно к thread_local объекту напрямую, а только к static мапе, линкеры выкидывают, по их мнению, не создающих внешнего эффекта конструкторы/деструкторы регистраторов.
Вопросы:
— прав ли я в своих догадках, или это что-то другое?
— как починить?
— может появилось что-то в С++17 для таких случаем, атрибуты там какие-нибудь или что-то похожее?
Если некий std::map, который объявлен как static в одном из С++ файлов. Также есть thread_local объект — регистратор, который всё что делает, в своём конструкторе регистрирует себя в static std::map, а в деструкторе разрегистрирует. Схема примерно такая:
[thread_local thread1_reg] --> [static std::map storage] <-- [thread_local thread2_reg]
В msvc- компилирует всё как задумано, вызывает конструкторы/деструкторы thread_local объекта в каждом потоке.
g++ и clang — вызывают конструктор/деструктор thread_local регистратора только для основного потока с main, во всех остальных потоках тишина.
У меня есть только одна догадка, что так как служебные потоки не обращаются непосредственно к thread_local объекту напрямую, а только к static мапе, линкеры выкидывают, по их мнению, не создающих внешнего эффекта конструкторы/деструкторы регистраторов.
Вопросы:
— прав ли я в своих догадках, или это что-то другое?
— как починить?
— может появилось что-то в С++17 для таких случаем, атрибуты там какие-нибудь или что-то похожее?
thread_local in C++17
Код вычистить пока не удалось, так что попробую пока своими словами. Появилась следующая проблема с thread_local объектом:
Если некий std::map, который объявлен как static в одном из С++ файлов. Также есть thread_local объект — регистратор, который всё что делает, в своём конструкторе регистрирует себя в static std::map, а в деструкторе разрегистрирует. Схема примерно такая:
В msvc- компилирует всё как задумано, вызывает конструкторы/деструкторы thread_local объекта в каждом потоке.
g++ и clang — вызывают конструктор/деструктор thread_local регистратора только для основного потока с main, во всех остальных потоках тишина.
У меня есть только одна догадка, что так как служебные потоки не обращаются непосредственно к thread_local объекту напрямую, а только к static мапе, линкеры выкидывают, по их мнению, не создающих внешнего эффекта конструкторы/деструкторы регистраторов.
Вопросы:
— прав ли я в своих догадках, или это что-то другое?
— как починить?
— может появилось что-то в С++17 для таких случаев, атрибуты там какие-нибудь или что-то похожее?
P.S. только что глянул ассебмлер: gcc реально создает объект в TLS только при первом обращении к thread_local объекту. Это так и должно быть? Можно ли как-то исхитрится и создавать объект как это делает "Студия", при запуске потока?
Если некий std::map, который объявлен как static в одном из С++ файлов. Также есть thread_local объект — регистратор, который всё что делает, в своём конструкторе регистрирует себя в static std::map, а в деструкторе разрегистрирует. Схема примерно такая:
[thread_local thread1_reg] --> [static std::map storage] <-- [thread_local thread2_reg]
В msvc- компилирует всё как задумано, вызывает конструкторы/деструкторы thread_local объекта в каждом потоке.
g++ и clang — вызывают конструктор/деструктор thread_local регистратора только для основного потока с main, во всех остальных потоках тишина.
У меня есть только одна догадка, что так как служебные потоки не обращаются непосредственно к thread_local объекту напрямую, а только к static мапе, линкеры выкидывают, по их мнению, не создающих внешнего эффекта конструкторы/деструкторы регистраторов.
Вопросы:
— прав ли я в своих догадках, или это что-то другое?
— как починить?
— может появилось что-то в С++17 для таких случаев, атрибуты там какие-нибудь или что-то похожее?
P.S. только что глянул ассебмлер: gcc реально создает объект в TLS только при первом обращении к thread_local объекту. Это так и должно быть? Можно ли как-то исхитрится и создавать объект как это делает "Студия", при запуске потока?