Продлить жизнь статической переменной в функции
От: Went  
Дата: 07.09.22 07:07
Оценка:
Здравствуйте. Хочется странного.
Есть функция — геттер синглтона:
Singleton& get_singleton()
{
  static Singleton s_singleton;
  return s_singleton;
}

По первому запросу объект создается, при разрушении статики — удаляется. Все хорошо.
Но иногда возникает ситуация, при которой происходят попытки обратиться к этому синглтону уже в процессе разрушения статики, и, иногда, уже после того, как переменная s_singleton разрушена.
Что делать? Я готов даже создавать новый экземпляр на куче или возвращать nullptr (допустим, функция возвращает указатель), но как надёжно определить тот факт, что статическая переменная уже разрушена? Можно поставить какой-то guard, который будет при разрушении ставить какую-то статическую переменную в особое состояние, но где гарантия, что дебагер, разрушая эту переменную, не затрёт её каким-то 0xDEADBEEF?
Re: Продлить жизнь статической переменной в функции
От: night beast СССР  
Дата: 07.09.22 07:19
Оценка:
Здравствуйте, Went, Вы писали:

W>Что делать? Я готов даже создавать новый экземпляр на куче или возвращать nullptr (допустим, функция возвращает указатель), но как надёжно определить тот факт, что статическая переменная уже разрушена? Можно поставить какой-то guard, который будет при разрушении ставить какую-то статическую переменную в особое состояние, но где гарантия, что дебагер, разрушая эту переменную, не затрёт её каким-то 0xDEADBEEF?


как предположение, можно этой какой-то переменной сделать указатель на Singleton и инициализировать адресом s_singleton
если дебагер перетрет значение, то оно будет отличаться от адреса s_singleton
Re: Продлить жизнь статической переменной в функции
От: · Великобритания  
Дата: 07.09.22 07:42
Оценка: +3 -1
Здравствуйте, Went, Вы писали:

W> Что делать?

Не использовать синглтоны и глобальные переменные.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: Продлить жизнь статической переменной в функции
От: Stanislav V. Zudin Россия  
Дата: 07.09.22 07:46
Оценка:
Здравствуйте, Went, Вы писали:

W>Есть функция — геттер синглтона:

W>По первому запросу объект создается, при разрушении статики — удаляется. Все хорошо.
W>Но иногда возникает ситуация, при которой происходят попытки обратиться к этому синглтону уже в процессе разрушения статики, и, иногда, уже после того, как переменная s_singleton разрушена.

W>Что делать?


Надо переходить на ручное управление.
Вместо статической локальной использовать переменную, к которой будут иметь доступ две функции: get_singleton() и destroy_singleton().
Конструировать её при первом обращении, как и раньше ( std::call_once() тебе в помощь).
А прибивать вручную, в правильном порядке, чтобы никто гарантированно не обратился к дохлой переменной.
_____________________
С уважением,
Stanislav V. Zudin
Re: Продлить жизнь статической переменной в функции
От: sergii.p  
Дата: 07.09.22 07:56
Оценка:
Здравствуйте, Went, Вы писали:

W>Здравствуйте. Хочется странного.

W>Но иногда возникает ситуация, при которой происходят попытки обратиться к этому синглтону уже в процессе разрушения статики, и, иногда, уже после того, как переменная s_singleton разрушена.

а как такая ситуация может возникнуть? Вы же уже из main вышли. Может не делать потоки detach и ждать их завершения до завершения main?
Re[2]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 07.09.22 08:04
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Надо переходить на ручное управление.

SVZ>Вместо статической локальной использовать переменную, к которой будут иметь доступ две функции: get_singleton() и destroy_singleton().
SVZ>Конструировать её при первом обращении, как и раньше ( std::call_once() тебе в помощь).
SVZ>А прибивать вручную, в правильном порядке, чтобы никто гарантированно не обратился к дохлой переменной.
Ну, как говорится, "мопед не мой", и я не могу определить этот порядок. Я знаю только то, что "в любой момент при разрушении статики кто-то в своём деструкторе может решить обратиться к этому синглтону". Я мог бы создать этот синглтон на куче и считать ссылки, но, опять же, я не имею возможности расставить инкремент и декремент ссылок так, чтобы гарантированно после последнего декремента никто не решил снова обратиться к этому объекту.
Re[2]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 07.09.22 08:06
Оценка:
Здравствуйте, sergii.p, Вы писали:
SP>а как такая ситуация может возникнуть? Вы же уже из main вышли. Может не делать потоки detach и ждать их завершения до завершения main?
Например, какой-то объект на статике в своём деструкторе решил записать что-то в лог (у меня не лог, но это не важно). То, что так делать не стоит — это другой вопрос, но для меня это данность.
Re[2]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 07.09.22 08:10
Оценка:
Здравствуйте, night beast, Вы писали:
NB>как предположение, можно этой какой-то переменной сделать указатель на Singleton и инициализировать адресом s_singleton
NB>если дебагер перетрет значение, то оно будет отличаться от адреса s_singleton
Разе мы тут не имеем тот же риск, что и с любым другим "особым" значением? Чем адрес синглтона принципиально отличается от любого другого magic word-а?
Re: Продлить жизнь статической переменной в функции
От: DiPaolo Россия  
Дата: 07.09.22 08:10
Оценка:
ИМХО, стоит подумать, как избежать обращения к статической переменной во время ее уничтожения. Сам по себе этот факт — тревожный звоночек, что что-то не так. И даже если вы сейчас решите свою проблему, потом могут вылезти другие.
Патриот здравого смысла
Re[3]: Продлить жизнь статической переменной в функции
От: Stanislav V. Zudin Россия  
Дата: 07.09.22 08:11
Оценка:
Здравствуйте, Went, Вы писали:

SVZ>>А прибивать вручную, в правильном порядке, чтобы никто гарантированно не обратился к дохлой переменной.

W>Ну, как говорится, "мопед не мой", и я не могу определить этот порядок. Я знаю только то, что "в любой момент при разрушении статики кто-то в своём деструкторе может решить обратиться к этому синглтону". Я мог бы создать этот синглтон на куче и считать ссылки, но, опять же, я не имею возможности расставить инкремент и декремент ссылок так, чтобы гарантированно после последнего декремента никто не решил снова обратиться к этому объекту.

Нууу... Если тебе нет необходимости освобождать какие-то ресурсы (т.е. обойтись без вызова деструктора), то ты можешь создавать свой синглетон не статиком, а в куче.
Тогда утечка памяти при закрытии приложения будет намеренной и неопасной, а синглетон точно переживёт всех.
_____________________
С уважением,
Stanislav V. Zudin
Re[3]: Продлить жизнь статической переменной в функции
От: so5team https://stiffstream.com
Дата: 07.09.22 08:13
Оценка: +5
Здравствуйте, Went, Вы писали:

SP>>а как такая ситуация может возникнуть? Вы же уже из main вышли. Может не делать потоки detach и ждать их завершения до завершения main?

W>Например, какой-то объект на статике в своём деструкторе решил записать что-то в лог (у меня не лог, но это не важно). То, что так делать не стоит — это другой вопрос, но для меня это данность.

Так ли важно, чтобы у объекта-синглетона вызывался деструктор?

Если не важно, то можно в функции-геттере синглетона однократно создавать объект в куче и никогда не удалять его. Да, память не будет освобождаться, но т.к. она все равно будет подчищена при завершении программы, то не все ли равно?
Re[3]: Продлить жизнь статической переменной в функции
От: night beast СССР  
Дата: 07.09.22 08:16
Оценка:
Здравствуйте, Went, Вы писали:

NB>>как предположение, можно этой какой-то переменной сделать указатель на Singleton и инициализировать адресом s_singleton

NB>>если дебагер перетрет значение, то оно будет отличаться от адреса s_singleton
W>Разе мы тут не имеем тот же риск, что и с любым другим "особым" значением? Чем адрес синглтона принципиально отличается от любого другого magic word-а?

я думаю что он не должен измениться при разрушении статики.
какое-нибудь константное инт тоже по идее не должно.
Re: Продлить жизнь статической переменной в функции
От: so5team https://stiffstream.com
Дата: 07.09.22 08:24
Оценка: 36 (6)
Здравствуйте, Went, Вы писали:

W>Что делать?


Счетчик Шварца еще не советовали?
Re[4]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 07.09.22 08:33
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>Нууу... Если тебе нет необходимости освобождать какие-то ресурсы (т.е. обойтись без вызова деструктора), то ты можешь создавать свой синглетон не статиком, а в куче.
SVZ>Тогда утечка памяти при закрытии приложения будет намеренной и неопасной, а синглетон точно переживёт всех.
Да, но есть момент. Синглтон thread_local, и при создании кучи тредов мы получим прогрессирующую утечку
Re[4]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 07.09.22 08:35
Оценка:
Здравствуйте, so5team, Вы писали:
S>Так ли важно, чтобы у объекта-синглетона вызывался деструктор?
S>Если не важно, то можно в функции-геттере синглетона однократно создавать объект в куче и никогда не удалять его. Да, память не будет освобождаться, но т.к. она все равно будет подчищена при завершении программы, то не все ли равно?
Синглтон thread_local и может весить очень много. При создании и удалении тредов можно получить прогрессирующую утечку.
Re[5]: Продлить жизнь статической переменной в функции
От: so5team https://stiffstream.com
Дата: 07.09.22 08:42
Оценка:
Здравствуйте, Went, Вы писали:

S>>Если не важно, то можно в функции-геттере синглетона однократно создавать объект в куче и никогда не удалять его. Да, память не будет освобождаться, но т.к. она все равно будет подчищена при завершении программы, то не все ли равно?

W>Синглтон thread_local и может весить очень много. При создании и удалении тредов можно получить прогрессирующую утечку.

А что, при завершении работы треда вызываются деструкторы статических объектов? Или у вас разрушаются thread_local объекты и обращение к вашему thread_local синглетону происходит из деструкторов именно этих объектов?
Re[2]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 07.09.22 08:45
Оценка:
Здравствуйте, so5team, Вы писали:
S>Счетчик Шварца еще не советовали?
Я о таком думал. Но есть ли гарантия, что при разрушении статики, система, работая в дебажной конфигурации, разрушая nifty_counter, не решит его забить каким-то мусором до того, как разрушится последний StreamInitializer? Или это касается только кучи?
Re[6]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 07.09.22 08:48
Оценка:
Здравствуйте, so5team, Вы писали:

S>А что, при завершении работы треда вызываются деструкторы статических объектов?

А разве при завершении треда thread_local объекты не разрушаются?

S>Или у вас разрушаются thread_local объекты и обращение к вашему thread_local синглетону происходит из деструкторов именно этих объектов?

Да, такое очень даже возможно.
Re[7]: Продлить жизнь статической переменной в функции
От: so5team https://stiffstream.com
Дата: 07.09.22 09:00
Оценка: +2
Здравствуйте, Went, Вы писали:

S>>А что, при завершении работы треда вызываются деструкторы статических объектов?

W>А разве при завершении треда thread_local объекты не разрушаются?

Так вы бы внесли ясность в тему: у вас thread_local или static объекты (или даже static thread_local). Потому что именно static объекты создаются при начале работы программы (до main) и разрушаются после выхода из main. Отдельная тема со static внутри функций, тут создание происходит при первом обращении к этой функции (или даже при первом входе в scope, в котором локальный static объект объявляется), но разрушаются такие объекты все равно после выхода из main. К тредам эти статические объекты, насколько я помню, отношения не имеют. Создание/разрушение тредов на них не сказывается.

https://wandbox.org/permlink/kLeo5BCuDX3l1z3X
Re[5]: Продлить жизнь статической переменной в функции
От: Stanislav V. Zudin Россия  
Дата: 07.09.22 09:07
Оценка: 4 (1)
Здравствуйте, Went, Вы писали:

SVZ>>Нууу... Если тебе нет необходимости освобождать какие-то ресурсы (т.е. обойтись без вызова деструктора), то ты можешь создавать свой синглетон не статиком, а в куче.

SVZ>>Тогда утечка памяти при закрытии приложения будет намеренной и неопасной, а синглетон точно переживёт всех.
W>Да, но есть момент. Синглтон thread_local, и при создании кучи тредов мы получим прогрессирующую утечку

Тогда вероятно стоит делать закат солнца вручную ручное распараллеливание синглетона на потоки.
Глобальный синглетон, внутри хеш с обработчиками (что у тебя этот синглетон должен делать), в качестве ключа std::thread::id.

А в thread_local — (де-)регистрация обработчиков, чтобы хеш чистился при завершении потоков.
Если поток по ключу не найден, то запрос обрабатывает специальный обработчик "для потеряшек".

Ну вот так как-то.
_____________________
С уважением,
Stanislav V. Zudin
Re[8]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 07.09.22 09:17
Оценка:
Здравствуйте, so5team, Вы писали:

S>Так вы бы внесли ясность в тему: у вас thread_local или static объекты (или даже static thread_local). Потому что именно static объекты создаются при начале работы программы (до main) и разрушаются после выхода из main. Отдельная тема со static внутри функций, тут создание происходит при первом обращении к этой функции (или даже при первом входе в scope, в котором локальный static объект объявляется), но разрушаются такие объекты все равно после выхода из main. К тредам эти статические объекты, насколько я помню, отношения не имеют. Создание/разрушение тредов на них не сказывается.


Пардон, всегда забудешь какие-то детали сразу. Да, у меня именно static thread_local.
Судя по небольшой доработке вашего кода: https://wandbox.org/permlink/stRAr75I7pPZnBaq, static thread_local разрушаются вместе с тредом, как я и ожидал. В моём коде это важно — синглтон должен помирать вместе со своим тредом.
Re[9]: Продлить жизнь статической переменной в функции
От: so5team https://stiffstream.com
Дата: 07.09.22 09:27
Оценка: +2
Здравствуйте, Went, Вы писали:

W>Пардон, всегда забудешь какие-то детали сразу. Да, у меня именно static thread_local.

W>Судя по небольшой доработке вашего кода: https://wandbox.org/permlink/stRAr75I7pPZnBaq, static thread_local разрушаются вместе с тредом, как я и ожидал. В моём коде это важно — синглтон должен помирать вместе со своим тредом.

Тогда остается только сказать, что ситуация интересная. Но, мне кажется, что вам за ее решение должны же заплатить. Соответственно, это ваша прямая рабочая обязанность найти решение, а не моя или кого-то другого с RSDN, уж простите мне мой французский.
Re: Продлить жизнь статической переменной в функции
От: Chorkov Россия  
Дата: 07.09.22 09:34
Оценка:
Здравствуйте, Went, Вы писали:


extern std::shared_ptr<Singleton> get_thread_singleton();

std::shared_ptr<Singleton> get_thread_singleton()
{
  thread_local std::shared_ptr<Singleton> s_singleton = std::make_shared<Singleton>();
  return s_singleton;
}


Все пользователи синглетона, (другие синглетоны) должны хранить (умный) указатель на него, полученный в конструкторе.
Re[2]: Продлить жизнь статической переменной в функции
От: DiPaolo Россия  
Дата: 07.09.22 10:28
Оценка: +2
S>Счетчик Шварца еще не советовали?

Все-таки можно еще на РСДНе узнавать что-то новое по технической части.

Спасибо
Патриот здравого смысла
Re: Продлить жизнь статической переменной в функции
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 07.09.22 11:32
Оценка: 2 (1)
Здравствуйте, Went, Вы писали:

W>По первому запросу объект создается, при разрушении статики — удаляется. Все хорошо.

У Александреску же был phoenix singleton, посмотри как он это сделал.
W>Что делать?
Как выше сказали, не использоваться синглтоны без крайней нужды, либо контролировать их создание и удаление в main.
Sic luceat lux!
Re[2]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 07.09.22 11:38
Оценка:
Здравствуйте, Chorkov, Вы писали:
C>Все пользователи синглетона, (другие синглетоны) должны хранить (умный) указатель на него, полученный в конструкторе.
Да нет никаких "пользователей". Случайная функция "залетает" из деструктора статического объекта и ей "внезапно" хочется этот синглтон.
Re[3]: Продлить жизнь статической переменной в функции
От: Ziaw Россия  
Дата: 07.09.22 11:45
Оценка:
Здравствуйте, Went, Вы писали:

W>Здравствуйте, Chorkov, Вы писали:

C>>Все пользователи синглетона, (другие синглетоны) должны хранить (умный) указатель на него, полученный в конструкторе.
W>Да нет никаких "пользователей". Случайная функция "залетает" из деструктора статического объекта и ей "внезапно" хочется этот синглтон.

Насколько я понимаю, нет никакого способа вызвать деструктор этого синглтона самой-самой последней операцией. Таким образом надо либо совсем отказаться от его уничтожения либо сделать так, чтобы он детерменировано освобождал ресурсы, а потом делал вид, что работает (не падал).
Re[3]: Продлить жизнь статической переменной в функции
От: Chorkov Россия  
Дата: 07.09.22 11:51
Оценка: 4 (1)
Здравствуйте, Went, Вы писали:

W>Здравствуйте, Chorkov, Вы писали:

C>>Все пользователи синглетона, (другие синглетоны) должны хранить (умный) указатель на него, полученный в конструкторе.
W>Да нет никаких "пользователей". Случайная функция "залетает" из деструктора статического объекта и ей "внезапно" хочется этот синглтон.

Вот этот второй статический объект, и будет владельцем первого синглетона.

Если я параильно понял, вот модель того что у вас происходит:
https://godbolt.org/z/nehjW1678

Раскомментируйте строку 25 и все исправиться.
Re[4]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 07.09.22 12:05
Оценка:
Здравствуйте, Chorkov, Вы писали:
C>Вот этот второй статический объект, и будет владельцем первого синглетона.
C>Если я параильно понял, вот модель того что у вас происходит:
C>https://godbolt.org/z/nehjW1678
C>Раскомментируйте строку 25 и все исправится.
Да, я уже прочитал про такой фокус, спасибо. Но у меня нет какой-то предсказуемой системы объектов, зависимостями которых я бы мог управлять. В любой момент любой пользователь библиотеки может дописать какой-то класс с деструктором на статике, который через какой-то рой колбэков или ещё чего-то потянет мой синглтон.
Re: Продлить жизнь статической переменной в функции
От: Teolog  
Дата: 07.09.22 13:46
Оценка: 2 (1)
-Аллоцировать нужный обьект на стеке потока самой первой строкой.
-Регистрировать в thread_local переменной
-дергать из этой переменной get функцией откуда надо, но лучше вообще-то передать ссылку явно.
Разрегистрировать на выходе из потока, а деструкнется он сам, самым последним.
Слово синглетон в отношений thread-local обьекта не применять, во избежании недопонимания.
Re[5]: Продлить жизнь статической переменной в функции
От: Chorkov Россия  
Дата: 07.09.22 14:05
Оценка: 4 (1)
Здравствуйте, Went, Вы писали:

W> Но у меня нет какой-то предсказуемой системы объектов, зависимостями которых я бы мог управлять. В любой момент любой пользователь библиотеки может дописать какой-то класс с деструктором на статике, который через какой-то рой колбэков или ещё чего-то потянет мой синглтон.



Тогда остаются три варианта:

1) Разрушать объекты не в самом теле потока, а в отдельном глобальном сборщике мусора.
(Можно подключиться к сигналам OS, о завершении потока.)

2) Можно заранее создать достаточно большой (но конечный) пул объектов, и выдавать один из пула, в зависимости от id потока.
(Возможны конфликты, что два потока используют один объект, но для некоторых сценариев это допустимо.)

3) Или создавать свой синглетон заведомо первым.
Это возможно, например, если вы владеете телом главной функции потока.
Если потоки, тоже создают пользователи — тогда указать, что первой строкой тела каждого потока, должен быть вызов ini_foo_library().

Если хотите написать библиотеку, пользователь которой вообще не сможет выстрелить себе в ногу — то это не о C++.
Re: Продлить жизнь статической переменной в функции
От: vsb Казахстан  
Дата: 07.09.22 16:42
Оценка: 3 (2)
Сделать глобальную переменную boolean, в деструкторе её взводить.
Re: Продлить жизнь статической переменной в функции
От: Reset  
Дата: 07.09.22 16:48
Оценка: +1 -2 :)
Sinleton должен быть shared_ptr.

Возвращать shared_from_this или просто копировать shared_ptr.

Почему старпер Охотников не догадывается до простых решений — я понимаю (слишком много умных статей прочитал, по-простому работать уже не умеет, да и вузовское образование накладывает отпечаток). А вот чё тут никто другой не может использовать простое решение из стандартной библиотеки... Видать Ковид на всех повлиял (или разумные люди из C++ довольно активно уходят — я, не сочтите за пропаганду, в Rust и веб).

P.S. Схлопывание ниши C++ и как результате его маргинализация — непреодолимая реальность.
Отредактировано 07.09.2022 21:20 Reset . Предыдущая версия .
Re[2]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 08.09.22 06:09
Оценка:
Здравствуйте, Reset, Вы писали:
R>Sinleton должен быть shared_ptr.
R>Возвращать shared_from_this или просто копировать shared_ptr.
Вы бы хотя бы условие задачи внимательно почитали и комментарии к нему... А вам все ковид, да С++-копцы мерещатся.
Re: Продлить жизнь статической переменной в функции
От: Went  
Дата: 08.09.22 06:24
Оценка:
Здравствуйте, все.

Короче, пока что остановился на варианте, когда объект-guard, сидящий рядом с синглтоном, при своей смерти явно удаляет синглтон и обнуляет указатель на него. И повторный вход в эту функцию, когда мы уже умерли-померли, диагностирует это через проверку указателя на ноль. Ну, а дальше, при необходимости можно уже или новый экземпляр создать, или просто ноль вернуть, там можно разрулить. Проблема в том, что остаётся вариант, когда дебаггер затрёт мой ноль мусором. Я так понимаю, теоретическую вероятность этого исключать нельзя?
Re: Продлить жизнь статической переменной в функции
От: Sm0ke Россия ksi
Дата: 08.09.22 19:54
Оценка:
Здравствуйте, Went, Вы писали:

W>Здравствуйте. Хочется странного.

W>Есть функция — геттер синглтона:
W>
W>Singleton& get_singleton()
W>{
W>  static Singleton s_singleton;
W>  return s_singleton;
W>}
W>

W>По первому запросу объект создается, при разрушении статики — удаляется. Все хорошо.
W>Но иногда возникает ситуация, при которой происходят попытки обратиться к этому синглтону уже в процессе разрушения статики, и, иногда, уже после того, как переменная s_singleton разрушена.
W>Что делать? Я готов даже создавать новый экземпляр на куче или возвращать nullptr (допустим, функция возвращает указатель), но как надёжно определить тот факт, что статическая переменная уже разрушена? Можно поставить какой-то guard, который будет при разрушении ставить какую-то статическую переменную в особое состояние, но где гарантия, что дебагер, разрушая эту переменную, не затрёт её каким-то 0xDEADBEEF?

А можно сделать рефакторинг и объединить все объекты, работающие с этим классом в одну структуру, чтобы сделать синглтон от этой всей структуры? Это вариант 1.

Вариант 2. Порядок уничтожения таких синглтонов обратен порядку их создания. Если нужен самый долгоживущий, то просто вызовите его раньше остальных.
Отредактировано 08.09.2022 19:55 Sm0ke . Предыдущая версия .
Re[2]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 09.09.22 07:47
Оценка:
Здравствуйте, Sm0ke, Вы писали:
S>А можно сделать рефакторинг и объединить все объекты, работающие с этим классом в одну структуру, чтобы сделать синглтон от этой всей структуры? Это вариант 1.
S>Вариант 2. Порядок уничтожения таких синглтонов обратен порядку их создания. Если нужен самый долгоживущий, то просто вызовите его раньше остальных.
Нет, я не могу ни рефакторинг проводить, ни гарантировать какой-то вызов "первым". Увы, я тесно зажат условиями, описанным в исходном сообщении.
Re[3]: Продлить жизнь статической переменной в функции
От: AleksandrN Россия  
Дата: 09.09.22 20:37
Оценка:
Здравствуйте, Went, Вы писали:

W>Здравствуйте, Chorkov, Вы писали:

C>>Все пользователи синглетона, (другие синглетоны) должны хранить (умный) указатель на него, полученный в конструкторе.
W>Да нет никаких "пользователей". Случайная функция "залетает" из деструктора статического объекта и ей "внезапно" хочется этот синглтон.

Есть несколько объектов, объявленных как static thread_local?
Вместо нескольких таких объектов, сделать один, который будет обёрткой над этими объектами и инициализировать и разрушать остальные в нужном порядке. А лучше подумать, как избавится от ситуации, когда к объекту, объявленному как thread static, обращаются не временные объекты, а другие статические объекты.
Re: Продлить жизнь статической переменной в функции
От: rg45 СССР  
Дата: 10.09.22 11:31
Оценка: 4 (1)
Здравствуйте, Went, Вы писали:

W>Здравствуйте. Хочется странного.

  Есть функция — геттер синглтона
W>
W>Singleton& get_singleton()
W>{
W>  static Singleton s_singleton;
W>  return s_singleton;
W>}
W>

W>По первому запросу объект создается, при разрушении статики — удаляется. Все хорошо.
W>Но иногда возникает ситуация, при которой происходят попытки обратиться к этому синглтону уже в процессе разрушения статики, и, иногда, уже после того, как переменная s_singleton разрушена.
W>Что делать? Я готов даже создавать новый экземпляр на куче или возвращать nullptr (допустим, функция возвращает указатель), но как надёжно определить тот факт, что статическая переменная уже разрушена? Можно поставить какой-то guard, который будет при разрушении ставить какую-то статическую переменную в особое состояние, но где гарантия, что дебагер, разрушая эту переменную, не затрёт её каким-то 0xDEADBEEF?

Если наш синглтон thread_local, то все танцы, связанные с синхронизацией отпадают. Тогда, думаю, достаточно будет просто сделать чуть более хитрую обертку (можно шаблонную):

http://coliru.stacked-crooked.com/a/36fdd30ff945e647

#include <iostream>

template <typename T>
T* get_singleton();

template <typename T>
class SingletonGuard
{
private:
    SingletonGuard() = default;
    SingletonGuard(const SingletonGuard&) = delete;
    ~SingletonGuard() { m_self_ptr = nullptr; };


    friend T* get_singleton<T>();

    T m_data{};
    static thread_local SingletonGuard m;
    static thread_local SingletonGuard* m_self_ptr;
};

template <typename T>
thread_local SingletonGuard<T> SingletonGuard<T>::m;

template <typename T>
thread_local SingletonGuard<T>* SingletonGuard<T>::m_self_ptr = &m;


template <typename T>
T* get_singleton()
{
    // Такая строгая проверка практически сводит к нулю вероятность использования "мертвого" указателя
    // на тот случай, если статическая память затирается каким-то специальным значением после использования.    
    return SingletonGuard<T>::m_self_ptr == &SingletonGuard<T>::m ? &SingletonGuard<T>::m.m_data : nullptr; 
    // Хотя, стого говоря, чтение значения из m_self_ptr, после окончания времени его жизни - это UB.
}

int main()
{
    std::cout << get_singleton<int>() << std::endl;
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 10.09.2022 15:44 rg45 . Предыдущая версия . Еще …
Отредактировано 10.09.2022 15:18 rg45 . Предыдущая версия .
Отредактировано 10.09.2022 15:04 rg45 . Предыдущая версия .
Отредактировано 10.09.2022 15:02 rg45 . Предыдущая версия .
Отредактировано 10.09.2022 14:57 rg45 . Предыдущая версия .
Отредактировано 10.09.2022 14:53 rg45 . Предыдущая версия .
Отредактировано 10.09.2022 11:43 rg45 . Предыдущая версия .
Отредактировано 10.09.2022 11:39 rg45 . Предыдущая версия .
Отредактировано 10.09.2022 11:34 rg45 . Предыдущая версия .
Re[2]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 10.09.22 19:33
Оценка:
Здравствуйте, rg45.
Да, я сделал по этому принципу — гард затирает указатель при разрушении.
Re[4]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 14.09.22 05:19
Оценка:
Здравствуйте, AleksandrN, Вы писали:

AN>Есть несколько объектов, объявленных как static thread_local?

Да, синглтон на каждый тред свой.

AN>Вместо нескольких таких объектов, сделать один, который будет обёрткой над этими объектами и инициализировать и разрушать остальные в нужном порядке.

Тогда этот объект придётся завести под мьютекс, чтобы в процессе доступа какой-то другой процесс не убил там чего-то или не добавил. А для меня синхронизация — непозволительная роскошь.

AN>А лучше подумать, как избавится от ситуации, когда к объекту, объявленному как thread static, обращаются не временные объекты, а другие статические объекты.

Никак не избавиться. Эта система слишком общая, чтобы её можно было чем-то принудительно ограничить. Представьте себе, например, логгер. Вы можете заставить кого-то запретить запись в лог в любой момент, когда ему это хочется?
Re[5]: Продлить жизнь статической переменной в функции
От: AleksandrN Россия  
Дата: 14.09.22 20:56
Оценка:
Здравствуйте, Went, Вы писали:

W>Тогда этот объект придётся завести под мьютекс, чтобы в процессе доступа какой-то другой процесс не убил там чего-то или не добавил. А для меня синхронизация — непозволительная роскошь.


Т.е. — к переменным, объявленным как static thread_local могут обращаться другие потоки? Каким образом это сделано и почему обращение к ним без синхронизации?

W>Никак не избавиться. Эта система слишком общая, чтобы её можно было чем-то принудительно ограничить. Представьте себе, например, логгер. Вы можете заставить кого-то запретить запись в лог в любой момент, когда ему это хочется?


Сделать одну точку выхода и закрывать лог после того, как прекратили работу все, кто может в него писать.
Re[6]: Продлить жизнь статической переменной в функции
От: Went  
Дата: 15.09.22 05:50
Оценка:
Здравствуйте, AleksandrN, Вы писали:

AN>Т.е. — к переменным, объявленным как static thread_local могут обращаться другие потоки? Каким образом это сделано и почему обращение к ним без синхронизации?

Объект создается в static thread_local коллекции одного потока, но потом передаётся для пользования в другой поток. И тот поток решает его убить. Почему без синхронизации — потому что синхронизация дорого, не дело, когда 75% от времени алгоритмов жрут мьютексы.

AN>Сделать одну точку выхода и закрывать лог после того, как прекратили работу все, кто может в него писать.

Я же говорю, что ограничить нельзя. Нет никакой "одной точки выхода". Это, по сути, библиотека, которую кто как захочет, так будет пользовать.

В любом случае, изначальный вопрос (продление жизни) я решил. Как писал выше — заложился на то, что компилятор не будет затирать мусором статические переменные потока до того, как последний статический элемент этого потока полностью будет разрушен (тавтология получается немного). А для решения вопроса блокировок сделал хитрый алгоритм на смеси блокирующих и неблокирующих подходов. Вроде работает. Только подразумевает атомарность записи указателя в память.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.