Информация об изменениях

Сообщение Re: Продлить жизнь статической переменной в функции от 10.09.2022 11:31

Изменено 10.09.2022 11:43 rg45

Re: Продлить жизнь статической переменной в функции
Здравствуйте, 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/426d1d6ecdb3f86a

#include <iostream>

template <typename T>
T* get_singleton();

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


    friend T* get_singleton<T>();

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

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

template <typename T>
thread_local T* SingletonGuard<T>::m_ptr = &m.m_data;


template <typename T>
T* get_singleton() { return SingletonGuard<T>::m_ptr; }

int main()
{
    std::cout << get_singleton<int>() << std::endl;
}
Re: Продлить жизнь статической переменной в функции
Здравствуйте, 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;    
}

int main()
{
    std::cout << get_singleton<int>() << std::endl;
}