Использование QtConcurrent для синглтонов

Я использую потокобезопасные синглтоны QObject в своем собственном проекте, и мне было интересно, правильно ли я поступаю, создавая их с использованием QtConcurrent, а не QMutex и QThread.

Вот как мне удается писать одноэлементный код.

class A : public QObject
{
 Q_OBJECT
 public:
         A() {}
         static A* sharedInstance() {
             static QFuture<A*> helper = QtConcurrent::run([]() -> A* {
                 auto *instance = new A();
                 instance->moveToThread(qApp->thread());
                 return instance;
             });
             return (A*)helper;
         }
 };

Это лучше, чем следующее?

class A : public QObject
{
 Q_OBJECT
 public:
         A() {}
         static A* sharedInstance() {
             static A* instance = 0;
             static QMutex mtx;
             mtx.lock();
             if (!instance) {
                instance = new A();
                instance->moveToThread(qApp->thread());
             }
             mtx.unlock();
             return instance;
         }
 };

Или есть ли другой лучший способ сделать это?

Спасибо.

ПРИМЕЧАНИЕ. Я обрабатываю уничтожение общего экземпляра отдельно.

EDIT: я хочу, чтобы общие экземпляры находились в основном потоке.


person alediaferia    schedule 06.06.2014    source источник
comment
Тогда вам не нужна безопасность потоков, и я вообще не вижу необходимости в этом коде.   -  person Kuba hasn't forgotten Monica    schedule 09.06.2014


Ответы (1)


Два фрагмента кода делают очень разные вещи. Первый создает новый экземпляр в рабочем потоке, а затем перемещает его в основной поток. Это делается, когда вызывающий поток блокируется для создания нового экземпляра. Я понятия не имею, зачем вам это делать, поскольку это не дает вам абсолютно ничего, кроме осложнений. Вызывающий поток блокирует не меньше, чем если бы вы создали экземпляр в вызывающем потоке. Это также не имеет ничего общего с синглтонами: sharedInstance будет возвращать новый экземпляр при каждом вызове.

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

Во всяком случае, второй вариант — это просто переизобретение Q_GLOBAL_STATIC без всякой причины. .

person Kuba hasn't forgotten Monica    schedule 07.06.2014
comment
Я редактирую свой вопрос: наличие экземпляра в основном потоке является для меня требованием. Для первого фрагмента кода я думаю, что static QFuture заставит лямбду запускаться только один раз. Таким образом, дальнейший доступ к общему экземпляру не будет включать блокировку мьютекса. Вместо этого второй блок включает блокировку мьютекса для каждого доступа. Я совсем не прав? - person alediaferia; 07.06.2014