Russian Qt Forum

Qt => Общие вопросы => Тема начата: BuRn от Декабря 07, 2014, 22:30



Название: Синглтон + сигналы QObject
Отправлено: BuRn от Декабря 07, 2014, 22:30
Есть синглтон, обычный, Маерса, делаю коннект на объект возвращаемый статическим методом getInstance, синглтон унаследован от QObject. Но вот почему-то сигналы не ловятся от него, мб кто сталкивался, в чем подвох?


Название: Re: Синглтон + сигналы QObject
Отправлено: kuzulis от Декабря 07, 2014, 22:52
Q_OBJECT макрос есть?


Название: Re: Синглтон + сигналы QObject
Отправлено: BuRn от Декабря 07, 2014, 22:55
Q_OBJECT макрос есть?
Да, если вы про класс


Название: Re: Синглтон + сигналы QObject
Отправлено: kambala от Декабря 08, 2014, 01:07
в консоль сыпятся ошибки коннекта?


Название: Re: Синглтон + сигналы QObject
Отправлено: __Heaven__ от Декабря 08, 2014, 07:37
Может тип коннекта задать другой?


Название: Re: Синглтон + сигналы QObject
Отправлено: Bepec от Декабря 08, 2014, 08:34
А вы точно привязываете сигналы-слоты к уже существующему объекту?


Название: Re: Синглтон + сигналы QObject
Отправлено: Пантер от Декабря 08, 2014, 08:36
Вон сколько вопросов пришлось задать. А привел бы код, сразу получил бы ответ.


Название: Re: Синглтон + сигналы QObject
Отправлено: BuRn от Декабря 08, 2014, 22:46
А вы точно привязываете сигналы-слоты к уже существующему объекту?
getInstance не может возвращать не существующий объект, в нем он как раз и создается если не создан.
В лог ошибок не сыпется.
сам синглтон:
Код:
class ManagerProxy: public QObject
{
    Q_OBJECT
public:
    static ManagerProxy *getInstance();
    QMap<QString,int> getProxy();
private:
    ManagerProxy();
    ~ManagerProxy();
    static ManagerProxy* instance;
    CollectorProxy collector;
    bool _locker;
    int _countFailLoadProxy;
private slots:
    void loadLiveProxy();
    void endLoadProxySlot();
signals:
    void emptyProxyList();
    void fullProxyList();
    void failLoadProxyList();
    void endLoadProxy();
};
ManagerProxy *ManagerProxy::getInstance()
{
    instance = new ManagerProxy();
    return instance;
}
connect(ManagerProxy::getInstance(),SIGNAL(fullProxyList()),this,SLOT(startLoadPagefromProxy()));


Название: Re: Синглтон + сигналы QObject
Отправлено: Old от Декабря 08, 2014, 23:10
Красиво. На каждый вызов getInstance новый объект.
Чудо-синглетон.


Название: Re: Синглтон + сигналы QObject
Отправлено: kambala от Декабря 08, 2014, 23:43
если я правильно помню, Мейерс рекомендует статическую стековую переменную в методе


Название: Re: Синглтон + сигналы QObject
Отправлено: Bepec от Декабря 09, 2014, 10:36
Согласен - чудо код, ещё и коннект прописан в месте, где ничего не создается вроде бы.
Хотя если честно впервые вижу коннект после описания класса.


Название: Re: Синглтон + сигналы QObject
Отправлено: GreatSnake от Декабря 09, 2014, 11:41
если я правильно помню, Мейерс рекомендует статическую стековую переменную в методе
"статическая стековая" - это что-то новенькое)
Наверное, всё-таки, "скоповая"?


Название: Re: Синглтон + сигналы QObject
Отправлено: kambala от Декабря 09, 2014, 13:39
наверное :) терминология хромает.

если память выделяем не в куче, значит стековая :)


Название: Re: Синглтон + сигналы QObject
Отправлено: GreatSnake от Декабря 09, 2014, 13:52
если память выделяем не в куче, значит стековая :)
Неправильно.
Штудируем "Организация памяти процесса (http://habrahabr.ru/company/smart_soft/blog/185226/)".


Название: Re: Синглтон + сигналы QObject
Отправлено: Igors от Декабря 09, 2014, 15:01
Неправильно.
Штудируем "Организация памяти процесса (http://habrahabr.ru/company/smart_soft/blog/185226/)".
Весьма сомнительная статейка :) Если "ближе к стандарту", то наверное "нелокальная переменная с локальной областью видимости". Хотя и так ясно что имелось ввиду, просто иногда хочется попридираться  :)


Название: Re: Синглтон + сигналы QObject
Отправлено: GreatSnake от Декабря 09, 2014, 15:23
Весьма сомнительная статейка :) Если "ближе к стандарту", то наверное "нелокальная переменная с локальной областью видимости". Хотя и так ясно что имелось ввиду, просто иногда хочется попридираться  :)
Статейка может и сомнительная, но в ней правильно сказано где хранятся статические данные.
И, да, придираюсь)
Особенно когда осознанно или нет высказываются такие мысли.


Название: Re: Синглтон + сигналы QObject
Отправлено: BuRn от Декабря 09, 2014, 18:13
Согласен - чудо код, ещё и коннект прописан в месте, где ничего не создается вроде бы.
Хотя если честно впервые вижу коннект после описания класса.
Да действительно с new косяк, а коннект я просто вынес из метода, дабы ненужные куски не включать


Название: Re: Синглтон + сигналы QObject
Отправлено: Hrundel от Декабря 10, 2014, 16:03
Попробуй с этим вариантом:

Код
C++ (Qt)
#ifndef SINGLETON_H
#define SINGLETON_H
 
#include <stddef.h>
 
template <class T>
class Singleton
{
   static T* _self;
   static int _refcount;
protected:
   Singleton(){}
   virtual ~Singleton(){_self = NULL;}
public:
   static T* Instance();
   void FreeInst();
};
 
template <class T>
T*  Singleton<T>::_self = NULL;
 
template <class T>
   int  Singleton<T>::_refcount=0;
 
template <class T>
T*  Singleton<T>::Instance()
{
     if(!_self) _self=new T;
     _refcount++;
     return _self;
}
 
template <class T>
void  Singleton<T>::FreeInst()
{
   if(--_refcount==0) delete this;
}
 
#endif // SINGLETON_H
 

Расширь его соответственно


Название: Re: Синглтон + сигналы QObject
Отправлено: m_ax от Декабря 10, 2014, 16:13
Попробуй с этим вариантом:

Код
C++ (Qt)
#ifndef SINGLETON_H
#define SINGLETON_H
 
#include <stddef.h>
 
template <class T>
class Singleton
{
   static T* _self;
   static int _refcount;
protected:
   Singleton(){}
   virtual ~Singleton(){_self = NULL;}
public:
   static T* Instance();
   void FreeInst();
};
 
template <class T>
T*  Singleton<T>::_self = NULL;
 
template <class T>
   int  Singleton<T>::_refcount=0;
 
template <class T>
T*  Singleton<T>::Instance()
{
     if(!_self) _self=new T;
     _refcount++;
     return _self;
}
 
template <class T>
void  Singleton<T>::FreeInst()
{
   if(--_refcount==0) delete this;
}
 
#endif // SINGLETON_H
 

Расширь его соответственно

Да, delete this - это сильно)


Название: Re: Синглтон + сигналы QObject
Отправлено: Пантер от Декабря 10, 2014, 16:16
Hrundel, не тредсэйф.


Название: Re: Синглтон + сигналы QObject
Отправлено: Hrundel от Декабря 10, 2014, 16:27
Hrundel, не тредсэйф.

У меня все прекрасно работает. В том виде в каком оно есть.


Название: Re: Синглтон + сигналы QObject
Отправлено: Old от Декабря 10, 2014, 17:43
У меня все прекрасно работает. В том виде в каком оно есть.
Это потому, что у вас несколько ниток одновременно не пытаются создать instance. А так их может быть создано несколько, несмотря на то что это синглетон. :)


Название: Re: Синглтон + сигналы QObject
Отправлено: Bepec от Декабря 10, 2014, 20:19
Old - если его могут создать несколько штук, он автоматом перестаёт быть сигнлтоном :)


Название: Re: Синглтон + сигналы QObject
Отправлено: Old от Декабря 10, 2014, 20:23
Old - если его могут создать несколько штук, он автоматом перестаёт быть сигнлтоном :)
Вот так в многопоточной среде синглетон теряет девственность.


Название: Re: Синглтон + сигналы QObject
Отправлено: m_ax от Декабря 10, 2014, 20:42
Вот классический вариант с использованием std::call_once

Код
C++ (Qt)
template <class T>
class singleton
{
public:
   static T& instance()
   {
       std::call_once(m_once_flag, [] { m_instance.reset(new T); });
       return *m_instance.get();
   }
 
   singleton() = delete;
   singleton(const singleton&) = delete;
   singleton& operator=(const singleton&) = delete;
 
private:
   static std::unique_ptr<T> m_instance;
   static std::once_flag m_once_flag;
};
 
template <class T>
std::unique_ptr<T> singleton<T>::m_instance;
 
template <class T>
std::once_flag singleton<T>::m_once_flag;
 


Название: Re: Синглтон + сигналы QObject
Отправлено: Hrundel от Декабря 11, 2014, 00:07
Вот классический вариант с использованием std::call_once

Код
C++ (Qt)
template <class T>
class singleton
{
public:
   static T& instance()
   {
       std::call_once(m_once_flag, [] { m_instance.reset(new T); });
       return *m_instance.get();
   }
 
   singleton() = delete;
   singleton(const singleton&) = delete;
   singleton& operator=(const singleton&) = delete;
 
private:
   static std::unique_ptr<T> m_instance;
   static std::once_flag m_once_flag;
};
 
template <class T>
std::unique_ptr<T> singleton<T>::m_instance;
 
template <class T>
std::once_flag singleton<T>::m_once_flag;
 

Спасибо, запишем, будем пользовать.


Название: Re: Синглтон + сигналы QObject
Отправлено: m_ax от Декабря 11, 2014, 00:41
Спасибо, запишем, будем пользовать.

Если честно, то я бы не стал этим пользоваться.. Этот код избыточен..
С таким же успехом можно написать и короче:
Код
C++ (Qt)
template <class T>
T& singleton()
{
   static T instance;
   return instance;
}
 


Название: Re: Синглтон + сигналы QObject
Отправлено: Hrundel от Декабря 11, 2014, 12:10
Код
C++ (Qt)
template <class T>
T& singleton()
{
   static T instance;
   return instance;
}
 

В этом варианте не вижу, где он проверяет сам себя на existenz


Название: Re: Синглтон + сигналы QObject
Отправлено: Пантер от Декабря 11, 2014, 12:12
А ему это не нужно, статическая переменная инициализируется только один раз.


Название: Re: Синглтон + сигналы QObject
Отправлено: Igors от Декабря 11, 2014, 12:19
Да, delete this - это сильно)
Это нормальная конструкция, никакого криминала здесь нет.

Если честно, то я бы не стал этим пользоваться.. Этот код избыточен..
Последние проблески здравого смысла  :)

С таким же успехом можно написать и короче:
Код
C++ (Qt)
template <class T>
T& singleton()
{
   static T instance;
   return instance;
}
 
И на древнем gcc 4.2 это можно было делать задолго до С++ 11. Опция "statics thread-safe" защищает вызов конструктора instance атомарным локом (напр OSSpinLockLock). И вся мудистика с call_once вероятно сводится к тому же. Что кстати совсем не идеальное решение.


Название: Re: Синглтон + сигналы QObject
Отправлено: m_ax от Декабря 11, 2014, 12:56
Цитировать
Это нормальная конструкция, никакого криминала здесь нет.
А кто говорит о криминале?
Вы посмотрите внимательнее на реализацию того синглетона, прежде чем заявлять, что это нормальная конструкция)

Цитировать
Последние проблески здравого смысла  :)

Ну куда уж мне до Вас, учитель..)

Цитировать
И вся мудистика с call_once вероятно сводится к тому же. Что кстати совсем не идеальное решение.
А мы увидим, интересно, идеальное решение от мастера? Ммм?

std::call_once избыточен даже из-за того, что можно было написать аналогично и без call_once:
Код
C++ (Qt)
template <class T>
class singleton
{
public:
   static T& instance()
   {
       static std::unique_ptr<T> instance(new T);
       return *instance.get();
   }
 
   singleton() = delete;
   singleton(const singleton&) = delete;
   singleton& operator=(const singleton&) = delete;
};
 
Но смысл?






Название: Re: Синглтон + сигналы QObject
Отправлено: Igors от Декабря 11, 2014, 13:48
Вы посмотрите внимательнее на реализацию того синглетона, прежде чем заявлять, что это нормальная конструкция)
Посмотрел. Не нравится как автор ставит пробелы - а ошибок не вижу. Да, эта реализация не thread-safe, ну этого никто и не обещал. Да и не синглтон это вовсе  :)

А мы увидим, интересно, идеальное решение от мастера? Ммм?
Здесь его достаточно услышать. Напомню из-за чего сыр-бор: мы почему-то упорно хотим объявить экземпляр внутри ф-ции/метода. Зачем? А вдруг мы никогда его не будем использовать - вот тогда сэкономим. Вы верите в такую экономию? (я нет). Реально потому что "std-дядя так сказал", а мы уже привыкли послушно делать все что дядя скажет  (и хвостик подымать на тех кто так не делает :)).

Решение 1: почему не просто объявить instance вне метода? Тогда конструктор вызовется до main, никаких проблем с "многопоточностью" нет.

Решение 2: Хорошо, не нравится до main, но что мешает вызвать getInstance() до запуска ниток? Этот момент всегда прекрасно известен и серия действий там всегда есть.

Оба решения не имеют накладных расходов на локи и.т.п. Но не тут-то было
std::call_once избыточен даже из-за того, что можно было написать аналогично и без call_once:
Код
C++ (Qt)
template <class T>
class singleton
{
public:
   static T& instance()
   {
       static std::unique_ptr<T> instance(new T);
       return *instance.get();
   }
 
   singleton() = delete;
   singleton(const singleton&) = delete;
   singleton& operator=(const singleton&) = delete;
};
 
Но смысл?
Смысл - загадить текст и сделать его недоступным для простых людей. Показать владение широким арсеналом средств, нисколько не смущаясь их неадекватностью в задаче.


Название: Re: Синглтон + сигналы QObject
Отправлено: Old от Декабря 11, 2014, 18:54
Да и не синглтон это вовсе  :)
Почему вы так подумали?

Реально потому что "std-дядя так сказал", а мы уже привыкли послушно делать все что дядя скажет  (и хвостик подымать на тех кто так не делает :)).
Если этот дядя вас будет уговаривать конфетками сесть к нем в машину не соглашайтесь. И тем более хвостик не поднимайте.

Решение 1: почему не просто объявить instance вне метода? Тогда конструктор вызовется до main, никаких проблем с "многопоточностью" нет.
Создание объекта до main не всегда хорошо. Например, перед созданием instance нам нужно выполнить некоторые действия или создать другие объекты, тот-же QApplication.
К тому же, порядок создания глобальных объектов не определен, если при конструировании одного глобального объекта используется другой глобальный объект, может случиться так, что используемый объект еще не будет сконструирован. Не так давно было обсуждение на форуме с такой ситуацией.
Ну и последнее, если instance никому не нужно, то и создаваться оно не должно.

Решение 2: Хорошо, не нравится до main, но что мешает вызвать getInstance() до запуска ниток? Этот момент всегда прекрасно известен и серия действий там всегда есть.
Опять же это предполагает обязательное создание instance, в этом случае можно оформлять синглетон по типу QCoreApplication. Позволит еще и любые параметры в конструктор передавать.

Оба решения не имеют накладных расходов на локи и.т.п.
Они имеют значительно большие накладные расходы в виде самого объекта instance.

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

А вообще, эту гадость (синглетон) лучше вообще не использовать. :)


Название: Re: Синглтон + сигналы QObject
Отправлено: Igors от Декабря 12, 2014, 10:15
Если этот дядя вас будет уговаривать конфетками сесть к нем в машину не соглашайтесь. И тем более хвостик не поднимайте.
Понял, учту Ваш опыт  :)

.. если при конструировании одного глобального объекта используется другой глобальный объект, может случиться так, что используемый объект еще не будет сконструирован.
Oбъявление экземпляра в локальной области видимости не избавляет от этой проблемы. Напр если синглтон использует qApp, и так и так вызывать его до создания qApp нельзя.

Они имеют значительно большие накладные расходы в виде самого объекта instance.
Что ж там такого страшного в instance? (часто пустой контейнер). Вы обобщаете очень редкий случай.

А вот нельзя загрузить либу как weak (delay loaded dll в Вындоуз) если у нее есть активные объекты до main. С этим я бы, пожалуй, согласился.


Название: Re: Синглтон + сигналы QObject
Отправлено: Old от Декабря 12, 2014, 13:18
Oбъявление экземпляра в локальной области видимости не избавляет от этой проблемы. Напр если синглтон использует qApp, и так и так вызывать его до создания qApp нельзя.
Как же не избавляют? Как раз избавляют. Мы точно знаем, когда будет создано instance, точнее оно будет создано когда мы этого захотим. Мы можем управлять этим процессом, чего нельзя сказать о глобальных объектах.

Что ж там такого страшного в instance? (часто пустой контейнер). Вы обобщаете очень редкий случай.
Это для вас редкий случай, а для меня был бы частым, если бы я пользовался этой дрянью. К тому же объект класса далеко не всегда является контейнером, тем более пустым. :)