summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qobject.cpp51
-rw-r--r--src/corelib/kernel/qobject.h41
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h52
3 files changed, 112 insertions, 32 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index b914ca812f..cc689657d2 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -854,9 +854,23 @@ QObject::~QObject()
senderLists->dirty = true;
int signal_index = node->signal_index;
+
+ QtPrivate::QSlotObjectBase *slotObj = Q_NULLPTR;
+ if (node->isSlotObject) {
+ slotObj = node->slotObj;
+ node->isSlotObject = false;
+ }
+
node = node->next;
if (needToUnlock)
m->unlock();
+
+ if (slotObj) {
+ locker.unlock();
+ slotObj->destroyIfLastRef();
+ locker.relock();
+ }
+
sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), signal_index));
}
}
@@ -4273,6 +4287,43 @@ void qDeleteInEventHandler(QObject *o)
*/
/*!
+ \fn QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type)
+
+ \threadsafe
+ \overload connect()
+
+ \since 5.2
+
+ Creates a connection of a given \a type from \a signal in
+ \a sender object to \a functor to be placed in a specific event
+ loop of \a context, and returns a handle to the connection
+
+ The signal must be a function declared as a signal in the header.
+ The slot function can be any function or functor that can be connected
+ to the signal.
+ A function can be connected to a given signal if the signal as at
+ least as many argument as the slot. A functor can be connected to a signal
+ if they have exactly the same number of arguments. There must exist implicit
+ conversion between the types of the corresponding arguments in the
+ signal and the slot.
+
+ Example:
+
+ \snippet code/src_corelib_kernel_qobject.cpp 50
+
+ If your compiler support C++11 lambda expressions, you can use them:
+
+ \snippet code/src_corelib_kernel_qobject.cpp 51
+
+ The connection will automatically disconnect if the sender or the context
+ is destroyed.
+
+ \note If the compiler does not support C++11 variadic templates, the number
+ of arguments in the signal or slot are limited to 6, and the functor object
+ must not have an overloaded or templated operator().
+ */
+
+/*!
\internal
Implementation of the template version of connect
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index 15b9c8f35e..e2000afc82 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -208,6 +208,7 @@ public:
#ifdef Q_QDOC
static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type);
static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor);
+ static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type);
#else
//Connect a signal to a pointer to qobject member function
template <typename Func1, typename Func2>
@@ -245,6 +246,16 @@ public:
static inline typename QtPrivate::QEnableIf<int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0, QMetaObject::Connection>::Type
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
{
+ return connect(sender, signal, sender, slot, Qt::DirectConnection);
+ }
+
+ //connect to a function pointer (not a member)
+ template <typename Func1, typename Func2>
+ static inline typename QtPrivate::QEnableIf<int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0 &&
+ !QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction, QMetaObject::Connection>::Type
+ connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
+ Qt::ConnectionType type = Qt::AutoConnection)
+ {
typedef QtPrivate::FunctionPointer<Func1> SignalType;
typedef QtPrivate::FunctionPointer<Func2> SlotType;
@@ -259,11 +270,15 @@ public:
Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
"Return type of the slot is not compatible with the return type of the signal.");
- return connectImpl(sender, reinterpret_cast<void **>(&signal), sender, 0,
+ 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), context, 0,
new QtPrivate::QStaticSlotObject<Func2,
typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
typename SignalType::ReturnType>(slot),
- Qt::DirectConnection, 0, &SignalType::Object::staticMetaObject);
+ type, types, &SignalType::Object::staticMetaObject);
}
//connect to a functor
@@ -271,6 +286,15 @@ public:
static inline typename QtPrivate::QEnableIf<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::Type
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
{
+ return connect(sender, signal, sender, slot, Qt::DirectConnection);
+ }
+
+ //connect to a functor, with a "context" object defining in which event loop is going to be executed
+ template <typename Func1, typename Func2>
+ static inline typename QtPrivate::QEnableIf<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::Type
+ connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
+ Qt::ConnectionType type = Qt::AutoConnection)
+ {
#if defined (Q_COMPILER_DECLTYPE) && defined (Q_COMPILER_VARIADIC_TEMPLATES)
typedef QtPrivate::FunctionPointer<Func1> SignalType;
const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Func2 , typename SignalType::Arguments>::Value;
@@ -292,9 +316,10 @@ public:
C++11 variadic templates
*/
#ifndef Q_COMPILER_DECLTYPE //Workaround the lack of decltype using another function as indirection
- return connect_functor(sender, signal, slot, &Func2::operator()); }
+ return connect_functor(sender, signal, context, slot, &Func2::operator(), type); }
template <typename Func1, typename Func2, typename Func2Operator>
- static inline QMetaObject::Connection connect_functor(const QObject *sender, Func1 signal, Func2 slot, Func2Operator) {
+ static inline QMetaObject::Connection connect_functor(const QObject *sender, Func1 signal, const QObject *context,
+ Func2 slot, Func2Operator, Qt::ConnectionType type) {
typedef QtPrivate::FunctionPointer<Func2Operator> SlotType ;
#else
typedef QtPrivate::FunctionPointer<decltype(&Func2::operator())> SlotType ;
@@ -315,11 +340,15 @@ public:
Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
"No Q_OBJECT in the class with the signal");
- return connectImpl(sender, reinterpret_cast<void **>(&signal), sender, 0,
+ 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), context, 0,
new QtPrivate::QFunctorSlotObject<Func2, SlotArgumentCount,
typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value,
typename SignalType::ReturnType>(slot),
- Qt::DirectConnection, 0, &SignalType::Object::staticMetaObject);
+ type, types, &SignalType::Object::staticMetaObject);
}
#endif //Q_QDOC
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h
index d775ef1b65..fb6601f21b 100644
--- a/src/corelib/kernel/qobjectdefs_impl.h
+++ b/src/corelib/kernel/qobjectdefs_impl.h
@@ -129,7 +129,7 @@ namespace QtPrivate {
its call function is the same as the FunctionPointer::call function.
*/
#ifndef Q_COMPILER_VARIADIC_TEMPLATES
- template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1}; };
+ template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; };
//Pointers to member functions
template<class Obj, typename Ret> struct FunctionPointer<Ret (Obj::*) ()>
{
@@ -137,7 +137,7 @@ namespace QtPrivate {
typedef void Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) ();
- enum {ArgumentCount = 0};
+ enum {ArgumentCount = 0, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue<R>(arg[0]); }
};
@@ -147,7 +147,7 @@ namespace QtPrivate {
typedef List<Arg1, void> Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1);
- enum {ArgumentCount = 1};
+ enum {ArgumentCount = 1, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)((*reinterpret_cast<typename RemoveRef<typename Args::Car>::Type *>(arg[1]))), ApplyReturnValue<R>(arg[0]);
@@ -159,7 +159,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, void> > Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1, Arg2);
- enum {ArgumentCount = 2};
+ enum {ArgumentCount = 2, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -172,7 +172,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3);
- enum {ArgumentCount = 3};
+ enum {ArgumentCount = 3, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -186,7 +186,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4);
- enum {ArgumentCount = 4};
+ enum {ArgumentCount = 4, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -201,7 +201,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > > Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5);
- enum {ArgumentCount = 5};
+ enum {ArgumentCount = 5, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -218,7 +218,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
- enum {ArgumentCount = 6};
+ enum {ArgumentCount = 6, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -237,7 +237,7 @@ namespace QtPrivate {
typedef void Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) () const;
- enum {ArgumentCount = 0};
+ enum {ArgumentCount = 0, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue<R>(arg[0]); }
};
@@ -247,7 +247,7 @@ namespace QtPrivate {
typedef List<Arg1, void> Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1) const;
- enum {ArgumentCount = 1};
+ enum {ArgumentCount = 1, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)((*reinterpret_cast<typename RemoveRef<typename Args::Car>::Type *>(arg[1]))), ApplyReturnValue<R>(arg[0]);
@@ -259,7 +259,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, void> > Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1, Arg2) const;
- enum {ArgumentCount = 2};
+ enum {ArgumentCount = 2, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -272,7 +272,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3) const;
- enum {ArgumentCount = 3};
+ enum {ArgumentCount = 3, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -286,7 +286,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4) const;
- enum {ArgumentCount = 4};
+ enum {ArgumentCount = 4, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -301,7 +301,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > > Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5) const;
- enum {ArgumentCount = 5};
+ enum {ArgumentCount = 5, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -318,7 +318,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const;
- enum {ArgumentCount = 6};
+ enum {ArgumentCount = 6, IsPointerToMemberFunction = true};
template <typename Args, typename R>
static void call(Function f, Obj *o, void **arg) {
(o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -336,7 +336,7 @@ namespace QtPrivate {
typedef void Arguments;
typedef Ret (*Function) ();
typedef Ret ReturnType;
- enum {ArgumentCount = 0};
+ enum {ArgumentCount = 0, IsPointerToMemberFunction = false};
template <typename Args, typename R>
static void call(Function f, void *, void **arg) { f(), ApplyReturnValue<R>(arg[0]); }
};
@@ -345,7 +345,7 @@ namespace QtPrivate {
typedef List<Arg1, void> Arguments;
typedef Ret ReturnType;
typedef Ret (*Function) (Arg1);
- enum {ArgumentCount = 1};
+ enum {ArgumentCount = 1, IsPointerToMemberFunction = false};
template <typename Args, typename R>
static void call(Function f, void *, void **arg)
{ f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1])), ApplyReturnValue<R>(arg[0]); }
@@ -355,7 +355,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, void> > Arguments;
typedef Ret ReturnType;
typedef Ret (*Function) (Arg1, Arg2);
- enum {ArgumentCount = 2};
+ enum {ArgumentCount = 2, IsPointerToMemberFunction = false};
template <typename Args, typename R>
static void call(Function f, void *, void **arg) {
f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -366,7 +366,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments;
typedef Ret ReturnType;
typedef Ret (*Function) (Arg1, Arg2, Arg3);
- enum {ArgumentCount = 3};
+ enum {ArgumentCount = 3, IsPointerToMemberFunction = false};
template <typename Args, typename R>
static void call(Function f, void *, void **arg) {
f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -379,7 +379,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments;
typedef Ret ReturnType;
typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4);
- enum {ArgumentCount = 4};
+ enum {ArgumentCount = 4, IsPointerToMemberFunction = false};
template <typename Args, typename R>
static void call(Function f, void *, void **arg) {
f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -394,7 +394,7 @@ namespace QtPrivate {
List<Arg4, List<Arg5, void > > > > > Arguments;
typedef Ret ReturnType;
typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5);
- enum {ArgumentCount = 5};
+ enum {ArgumentCount = 5, IsPointerToMemberFunction = false};
template <typename Args, typename R>
static void call(Function f, void *, void **arg) {
f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -409,7 +409,7 @@ namespace QtPrivate {
typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments;
typedef Ret ReturnType;
typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
- enum {ArgumentCount = 6};
+ enum {ArgumentCount = 6, IsPointerToMemberFunction = false};
template <typename Args, typename R>
static void call(Function f, void *, void **arg) {
f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
@@ -493,7 +493,7 @@ namespace QtPrivate {
template <int N> struct Indexes
{ typedef typename IndexesAppend<typename Indexes<N - 1>::Value, N - 1>::Value Value; };
template <> struct Indexes<0> { typedef IndexesList<> Value; };
- template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1}; };
+ template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; };
template <typename, typename, typename, typename> struct FunctorCall;
template <int... II, typename... SignalArgs, typename R, typename Function>
@@ -521,7 +521,7 @@ namespace QtPrivate {
typedef List<Args...> Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Args...);
- enum {ArgumentCount = sizeof...(Args)};
+ enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true};
template <typename SignalArgs, typename R>
static void call(Function f, Obj *o, void **arg) {
FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, o, arg);
@@ -533,7 +533,7 @@ namespace QtPrivate {
typedef List<Args...> Arguments;
typedef Ret ReturnType;
typedef Ret (Obj::*Function) (Args...) const;
- enum {ArgumentCount = sizeof...(Args)};
+ enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true};
template <typename SignalArgs, typename R>
static void call(Function f, Obj *o, void **arg) {
FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, o, arg);
@@ -545,7 +545,7 @@ namespace QtPrivate {
typedef List<Args...> Arguments;
typedef Ret ReturnType;
typedef Ret (*Function) (Args...);
- enum {ArgumentCount = sizeof...(Args)};
+ enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = false};
template <typename SignalArgs, typename R>
static void call(Function f, void *, void **arg) {
FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, arg);