Требование, чтобы "someOperation is not reentrant"
было нечетным. Что должно произойти, если попытка возвращения? Учитывая, что someOperation
может вызываться только из потока main
, я вижу только два варианта ...
- Блокируйте полностью мьютексом / барьером и т. Д., Как вы пытались.
- Блок основан на счетчике уровня рекурсии и вращает цикл событий, пока этот счетчик не уменьшится до нуля.
1) Полностью заблокирует цикл событий потока, не позволяя текущему диалоговому окну функционировать правильно.
2) Разрешает одновременное ведение всех диалогов сообщений, а не их сериализацию.
Вместо того, чтобы пытаться сделать someOperation
не реентерабельным, я думаю, вам нужно убедиться, что вы используете его так, чтобы это не привело к реентерабельности.
Одним из вариантов может быть использование отдельного QObject
производного экземпляра класса самостоятельно QThread
. Подумайте о следующем ...
class signal_serialiser: public QObject {
Q_OBJECT;
signals:
void signal1();
void signal2();
void signal3();
};
Если экземпляр signal_serialiser
перемещен в собственный поток, он может выступать в качестве очереди для буферизации и пересылки различных сигналов, если используются подходящие типы соединений. В вашем коде у вас есть ...
QObject::connect(w, SIGNAL(signal1()), a, SLOT(slot1()), Qt::QueuedConnection);
QObject::connect(w, SIGNAL(signal2()), a, SLOT(slot2()), Qt::QueuedConnection);
QObject::connect(w, SIGNAL(signal3()), a, SLOT(slot3()), Qt::QueuedConnection);
Измените это на ...
signal_serialiser signal_serialiser;
QObject::connect(w, SIGNAL(signal1()), &signal_serialiser, SIGNAL(signal1()));
QObject::connect(w, SIGNAL(signal2()), &signal_serialiser, SIGNAL(signal2()));
QObject::connect(w, SIGNAL(signal3()), &signal_serialiser, SIGNAL(signal3()));
/*
* Note the use of Qt::BlockingQueuedConnection for the
* signal_serialiser --> A connections.
*/
QObject::connect(&signal_serialiser, SIGNAL(signal1()), a, SLOT(slot1()), Qt::BlockingQueuedConnection);
QObject::connect(&signal_serialiser, SIGNAL(signal2()), a, SLOT(slot2()), Qt::BlockingQueuedConnection);
QObject::connect(&signal_serialiser, SIGNAL(signal3()), a, SLOT(slot3()), Qt::BlockingQueuedConnection);
QThread signal_serialiser_thread;
signal_serialiser.moveToThread(&signal_serialiser_thread);
signal_serialiser_thread.start();
Я только что провел базовое тестирование, но, похоже, оно дает желаемое поведение.