Re[5]: Поясните за деструкторы thread_local (3.6.3/1)
От: Кодт Россия  
Дата: 16.03.17 15:54
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Получается, это может не работать

AG>static GlobalData g_GlobalData;
AG>static thread_local ThreadData g_ThreadData; // ThreadData использует g_GlobalData

Ну да.

Советую заглянуть в книгу Александреску Modern C++ Design (Современное программирование на С++).
Там целая глава посвящена разным синглетонам. И то, он не учитывал работу с динамическими модулями (dll/so), из-за чего его библиотека Loki крешилась. Но общую картину осветил хорошо, — просто не сделал последнего шага.

По сути, стандарт говорит, что компилятор может втихую заменить нелокальные переменные на синглетоны Мейерса. Со всеми вытекающими из этого последствиями.
А чтобы посторонние потоки не создавали экземпляры ThreadData без нужды, вот тут явные синглетоны по требованию — хоть Мейерса, хоть что-то более продвинутое, — пригодятся.

А что касается shared_ptr<GlobalData>,

Если к нему обращаться в конструкторе и в той же единице трансляции, то компилятор просто обязан создать GlobalData (и зарегистрировать его в atexit) до выхода из конструктора ThreadData и, соответственно, до регистрации того в atexit.
Поэтому деструкторы всех ThreadData выполнятся до деструктора GlobalData. То есть, shared_ptr избыточен.
Если запоминать shared_ptr как член при первом реальном обращении, — то нужно лишь обеспечить, что это первое реальное обращение не во время atexit. Либо делать синглетон-феникс.

Однако, есть рацио в том, чтобы делать именно член — shared_ptr. Это если объекты раскиданы по разным единицам трансляции.
Тут уже компилятор не будет гарантировать правильный порядок создания нелокальных объектов, а синглетоны Мейерса — вынужденно будут.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.