Add support for QueuedConnection when connecting using the new syntax
QMetaCallEvent now can handle a pointer to QSlotObjectBase Change-Id: I94da1e68ce9bb1fd96a9ae013a389552eb625faa Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
583c55b243
commit
66b659c8a4
@ -498,11 +498,23 @@ void QObjectPrivate::clearGuards(QObject *object)
|
||||
QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction,
|
||||
const QObject *sender, int signalId,
|
||||
int nargs, int *types, void **args, QSemaphore *semaphore)
|
||||
: QEvent(MetaCall), sender_(sender), signalId_(signalId),
|
||||
: QEvent(MetaCall), slotObj_(0), sender_(sender), signalId_(signalId),
|
||||
nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
|
||||
callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative)
|
||||
{ }
|
||||
|
||||
/*! \internal
|
||||
*/
|
||||
QMetaCallEvent::QMetaCallEvent(QObject::QSlotObjectBase *slotO, const QObject *sender, int signalId,
|
||||
int nargs, int *types, void **args, QSemaphore *semaphore)
|
||||
: QEvent(MetaCall), slotObj_(slotO), sender_(sender), signalId_(signalId),
|
||||
nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
|
||||
callFunction_(0), method_offset_(0), method_relative_(-1)
|
||||
{
|
||||
if (slotObj_)
|
||||
slotObj_->ref.ref();
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
*/
|
||||
QMetaCallEvent::~QMetaCallEvent()
|
||||
@ -519,13 +531,17 @@ QMetaCallEvent::~QMetaCallEvent()
|
||||
if (semaphore_)
|
||||
semaphore_->release();
|
||||
#endif
|
||||
if (slotObj_ && !slotObj_->ref.deref())
|
||||
delete slotObj_;
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
*/
|
||||
void QMetaCallEvent::placeMetaCall(QObject *object)
|
||||
{
|
||||
if (callFunction_) {
|
||||
if (slotObj_) {
|
||||
slotObj_->call(object, args_);
|
||||
} else if (callFunction_) {
|
||||
callFunction_(object, QMetaObject::InvokeMetaMethod, method_relative_, args_);
|
||||
} else {
|
||||
QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method_offset_ + method_relative_, args_);
|
||||
@ -3261,11 +3277,10 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
|
||||
args[0] = 0; // return value
|
||||
for (int n = 1; n < nargs; ++n)
|
||||
args[n] = QMetaType::create((types[n] = argumentTypes[n-1]), argv[n]);
|
||||
QCoreApplication::postEvent(c->receiver, new QMetaCallEvent(c->method_offset,
|
||||
c->method_relative,
|
||||
c->callFunction,
|
||||
sender, signal, nargs,
|
||||
types, args));
|
||||
QMetaCallEvent *ev = c->isSlotObject ?
|
||||
new QMetaCallEvent(c->slotObj, sender, signal, nargs, types, args) :
|
||||
new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs, types, args);
|
||||
QCoreApplication::postEvent(c->receiver, ev);
|
||||
}
|
||||
|
||||
|
||||
@ -3378,12 +3393,10 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
|
||||
receiver->metaObject()->className(), receiver);
|
||||
}
|
||||
QSemaphore semaphore;
|
||||
QCoreApplication::postEvent(receiver, new QMetaCallEvent(c->method_offset, c->method_relative,
|
||||
c->callFunction,
|
||||
sender, signal_absolute_index,
|
||||
0, 0,
|
||||
argv ? argv : empty_argv,
|
||||
&semaphore));
|
||||
QMetaCallEvent *ev = c->isSlotObject ?
|
||||
new QMetaCallEvent(c->slotObj, sender, signal_absolute_index, 0, 0, argv ? argv : empty_argv, &semaphore) :
|
||||
new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_absolute_index, 0, 0, argv ? argv : empty_argv, &semaphore);
|
||||
QCoreApplication::postEvent(receiver, ev);
|
||||
semaphore.acquire();
|
||||
locker.relock();
|
||||
continue;
|
||||
|
@ -221,6 +221,9 @@ public:
|
||||
typedef typename QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::IncompatibleSignalSlotArguments EnsureCompatibleArguments;
|
||||
|
||||
const int *types = 0;
|
||||
if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
|
||||
types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
|
||||
|
||||
return connectImpl(sender, reinterpret_cast<void **>(&signal),
|
||||
receiver, new QSlotObject<Func2,
|
||||
typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
|
||||
@ -318,6 +321,7 @@ protected:
|
||||
static const QMetaObject staticQtMetaObject;
|
||||
|
||||
friend struct QMetaObject;
|
||||
friend class QMetaCallEvent;
|
||||
friend class QApplication;
|
||||
friend class QApplicationPrivate;
|
||||
friend class QCoreApplication;
|
||||
|
@ -344,6 +344,43 @@ namespace QtPrivate {
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
Logic to statically generate the array of qMetaTypeId
|
||||
ConnectionTypes<FunctionPointer<Signal>::Arguments>::types() returns an array
|
||||
of int that is suitable for the types arguments of the connection functions.
|
||||
|
||||
The array only exist of all the types are declared as a metatype
|
||||
(detected using the TypesAreDeclaredMetaType helper struct)
|
||||
If one of the type is not declared, the function return 0 and the signal
|
||||
cannot be used in queued connection.
|
||||
*/
|
||||
#ifndef Q_COMPILER_VARIADIC_TEMPLATES
|
||||
template <typename ArgList> struct TypesAreDeclaredMetaType { enum { Value = false }; };
|
||||
template <> struct TypesAreDeclaredMetaType<void> { enum { Value = true }; };
|
||||
template <typename Arg, typename Tail> struct TypesAreDeclaredMetaType<List<Arg, Tail> > { enum { Value = QMetaTypeId2<Arg>::Defined && TypesAreDeclaredMetaType<Tail>::Value }; };
|
||||
|
||||
template <typename ArgList, bool Declared = TypesAreDeclaredMetaType<ArgList>::Value > struct ConnectionTypes
|
||||
{ static const int *types() { return 0; } };
|
||||
template <> struct ConnectionTypes<void, true>
|
||||
{ static const int *types() { static const int t[1] = { 0 }; return t; } };
|
||||
template <typename Arg1> struct ConnectionTypes<List<Arg1, void>, true>
|
||||
{ static const int *types() { static const int t[2] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), 0 }; return t; } };
|
||||
template <typename Arg1, typename Arg2> struct ConnectionTypes<List<Arg1, List<Arg2, void> >, true>
|
||||
{ static const int *types() { static const int t[3] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(), 0 }; return t; } };
|
||||
template <typename Arg1, typename Arg2, typename Arg3> struct ConnectionTypes<List<Arg1, List<Arg2, List<Arg3, void> > >, true>
|
||||
{ static const int *types() { static const int t[4] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(),
|
||||
QtPrivate::QMetaTypeIdHelper<Arg3>::qt_metatype_id(), 0 }; return t; } };
|
||||
#else
|
||||
template <typename ArgList> struct TypesAreDeclaredMetaType { enum { Value = false }; };
|
||||
template <> struct TypesAreDeclaredMetaType<List<>> { enum { Value = true }; };
|
||||
template <typename Arg, typename... Tail> struct TypesAreDeclaredMetaType<List<Arg, Tail...> >
|
||||
{ enum { Value = QMetaTypeId2<Arg>::Defined && TypesAreDeclaredMetaType<List<Tail...>>::Value }; };
|
||||
|
||||
template <typename ArgList, bool Declared = TypesAreDeclaredMetaType<ArgList>::Value > struct ConnectionTypes
|
||||
{ static const int *types() { return 0; } };
|
||||
template <typename... Args> struct ConnectionTypes<List<Args...>, true>
|
||||
{ static const int *types() { static const int t[sizeof...(Args) + 1] = { (QtPrivate::QMetaTypeIdHelper<Args>::qt_metatype_id())..., 0 }; return t; } };
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -264,6 +264,9 @@ class Q_CORE_EXPORT QMetaCallEvent : public QEvent
|
||||
public:
|
||||
QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId,
|
||||
int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
|
||||
QMetaCallEvent(QObject::QSlotObjectBase *slotObj, const QObject *sender, int signalId,
|
||||
int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
|
||||
|
||||
~QMetaCallEvent();
|
||||
|
||||
inline int id() const { return method_offset_ + method_relative_; }
|
||||
@ -274,6 +277,7 @@ public:
|
||||
virtual void placeMetaCall(QObject *object);
|
||||
|
||||
private:
|
||||
QObject::QSlotObjectBase *slotObj_;
|
||||
const QObject *sender_;
|
||||
int signalId_;
|
||||
int nargs_;
|
||||
|
@ -2812,6 +2812,10 @@ void tst_QObject::blockingQueuedConnection()
|
||||
QVERIFY(QMetaObject::invokeMethod(&receiver, "slot1", Qt::BlockingQueuedConnection));
|
||||
QVERIFY(receiver.called(1));
|
||||
|
||||
connect(&sender, &SenderObject::signal2, &receiver, &ReceiverObject::slot2, Qt::BlockingQueuedConnection);
|
||||
sender.emitSignal2();
|
||||
QVERIFY(receiver.called(2));
|
||||
|
||||
thread.quit();
|
||||
QVERIFY(thread.wait());
|
||||
}
|
||||
@ -4173,6 +4177,29 @@ void tst_QObject::customTypesPointer()
|
||||
QCOMPARE(checker.received.value(), 0);
|
||||
checker.doEmit(t1);
|
||||
QCOMPARE(checker.received.value(), t1.value());
|
||||
checker.received = t0;
|
||||
|
||||
|
||||
checker.disconnect();
|
||||
|
||||
int idx = qRegisterMetaType<CustomType>("CustomType");
|
||||
QCOMPARE(QMetaType::type("CustomType"), idx);
|
||||
|
||||
connect(&checker, &QCustomTypeChecker::signal1, &checker, &QCustomTypeChecker::slot1,
|
||||
Qt::QueuedConnection);
|
||||
QCOMPARE(instanceCount, 4);
|
||||
checker.doEmit(t2);
|
||||
QCOMPARE(instanceCount, 5);
|
||||
QCOMPARE(checker.received.value(), t0.value());
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
QCOMPARE(checker.received.value(), t2.value());
|
||||
QCOMPARE(instanceCount, 4);
|
||||
|
||||
QVERIFY(QMetaType::isRegistered(idx));
|
||||
QCOMPARE(qRegisterMetaType<CustomType>("CustomType"), idx);
|
||||
QCOMPARE(QMetaType::type("CustomType"), idx);
|
||||
QVERIFY(QMetaType::isRegistered(idx));
|
||||
}
|
||||
QCOMPARE(instanceCount, 3);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user