Fix Qt::QueuedConnection when signal has a return value

For queued connections, the args[0] is set to null as it make no sens to
forward the return value to the signal.
So we need to check in the operator, that the pointer is not null.
(container.data is args[0])

Change-Id: I80bde66f1ec19de0f4962c80e5b2797d2819075c
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
This commit is contained in:
Olivier Goffart 2011-11-29 01:44:18 +01:00 committed by Qt by Nokia
parent fa7f690178
commit 55b974faa1
2 changed files with 61 additions and 2 deletions

View File

@ -96,12 +96,14 @@ namespace QtPrivate {
};
template<typename T, typename U>
void operator,(const T &value, const ApplyReturnValue<U> &container) {
*reinterpret_cast<U*>(container.data) = value;
if (container.data)
*reinterpret_cast<U*>(container.data) = value;
}
#ifdef Q_COMPILER_RVALUE_REFS
template<typename T, typename U>
void operator,(T &&value, const ApplyReturnValue<U> &container) {
*reinterpret_cast<U*>(container.data) = value;
if (container.data)
*reinterpret_cast<U*>(container.data) = value;
}
#endif
template<typename T>

View File

@ -4978,6 +4978,29 @@ void tst_QObject::returnValue()
QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnVoidSlot, type));
QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
}
if (!isBlockingQueued) {
// queued connection should not forward the return value
CheckInstanceCount checker;
ReturnValue r;
QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, Qt::QueuedConnection));
QCOMPARE(emit r.returnVariant(45), QVariant());
QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnStringSlot, Qt::QueuedConnection));
QCOMPARE(emit r.returnString(45), QString());
QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, Qt::QueuedConnection));
QCOMPARE(emit r.returnInt(45), int());
QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnCustomTypeSlot, Qt::QueuedConnection));
QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
QCoreApplication::processEvents();
QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnStringSlot, Qt::QueuedConnection));
QCOMPARE(emit r.returnVariant(48), QVariant());
QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnIntSlot, Qt::QueuedConnection));
QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value());
QVERIFY(connect(&r, &ReturnValue::returnVoid, &receiver, &ReturnValue::returnCustomTypeSlot, Qt::QueuedConnection));
emit r.returnVoid(48);
QCoreApplication::processEvents();
}
{ // connected to many slots
ReturnValue::VoidFunctor voidFunctor;
ReturnValue::IntFunctor intFunctor;
@ -4994,6 +5017,8 @@ void tst_QObject::returnValue()
QCOMPARE(emit r.returnVariant(45), QVariant(QStringLiteral("hello")));
QVERIFY(connect(&r, &ReturnValue::returnVariant, intFunctor));
QCOMPARE(emit r.returnVariant(45), QVariant(45));
QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::return23, Qt::QueuedConnection));
QCOMPARE(emit r.returnVariant(45), QVariant(45));
QCOMPARE(emit r.returnInt(45), int());
QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnVoidSlot, type));
@ -5006,7 +5031,12 @@ void tst_QObject::returnValue()
QCOMPARE(emit r.returnInt(45), int(23));
QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor));
QCOMPARE(emit r.returnInt(45), int(45));
QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::return23, Qt::QueuedConnection));
QCOMPARE(emit r.returnInt(45), int(45));
QCoreApplication::processEvents();
}
if (isBlockingQueued) {
thread.quit();
thread.wait();
@ -5055,6 +5085,29 @@ void tst_QObject::returnValue2()
QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnVoidSlot()), type));
QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
}
if (!isBlockingQueued) {
// queued connection should not forward the return value
CheckInstanceCount checker;
ReturnValue r;
QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVariantSlot(int)), Qt::QueuedConnection));
QCOMPARE(emit r.returnVariant(45), QVariant());
QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
QCOMPARE(emit r.returnString(45), QString());
QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
QCOMPARE(emit r.returnInt(45), int());
QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection));
QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
QCoreApplication::processEvents();
//Queued conneciton with different return type should be safe
QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
QCOMPARE(emit r.returnVariant(48), QVariant());
QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value());
QVERIFY(connect(&r, SIGNAL(returnVoid(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection));
emit r.returnVoid(48);
QCoreApplication::processEvents();
}
{ // connected to many slots
ReturnValue r;
QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), type));
@ -5063,6 +5116,8 @@ void tst_QObject::returnValue2()
QCOMPARE(emit r.returnInt(45), int(45));
QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(return23()), type));
QCOMPARE(emit r.returnInt(45), int(23));
QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
QCOMPARE(emit r.returnInt(45), int(23));
QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), type));
QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45")));
@ -5070,6 +5125,8 @@ void tst_QObject::returnValue2()
QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45")));
QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnHello()), type));
QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello")));
QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello")));
}
if (isBlockingQueued) {
thread.quit();