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.
Да, я сделал по этому принципу — гард затирает указатель при разрушении.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.