diff options
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 32 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.h | 56 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_impl.h | 98 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 6 |
4 files changed, 120 insertions, 72 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index a00d528ec9..6ac29879b9 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -72,6 +72,11 @@ QT_BEGIN_NAMESPACE static int DIRECT_CONNECTION_ONLY = 0; +struct QSlotObjectBaseDeleter { // for use with QScopedPointer<QSlotObjectBase,...> + static void cleanup(QtPrivate::QSlotObjectBase *slot) { + if (slot && !slot->ref.deref() ) slot->destroy(); + } +}; static int *queuedConnectionTypes(const QList<QByteArray> &typeNames) { int *types = new int [typeNames.count() + 1]; @@ -432,7 +437,7 @@ QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QOb /*! \internal */ -QMetaCallEvent::QMetaCallEvent(QObject::QSlotObjectBase *slotO, const QObject *sender, int signalId, +QMetaCallEvent::QMetaCallEvent(QtPrivate::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), @@ -460,7 +465,7 @@ QMetaCallEvent::~QMetaCallEvent() semaphore_->release(); #endif if (slotObj_ && !slotObj_->ref.deref()) - delete slotObj_; + slotObj_->destroy(); } /*! @@ -864,7 +869,7 @@ QObjectPrivate::Connection::~Connection() delete [] v; } if (isSlotObject && !slotObj->ref.deref()) - delete slotObj; + slotObj->destroy(); } @@ -3412,7 +3417,8 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction; const int method_relative = c->method_relative; if (c->isSlotObject) { - QExplicitlySharedDataPointer<QObject::QSlotObjectBase> obj(c->slotObj); + c->slotObj->ref.ref(); + const QScopedPointer<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> obj(c->slotObj); locker.unlock(); obj->call(receiver, argv ? argv : empty_argv); locker.relock(); @@ -4185,13 +4191,13 @@ void qDeleteInEventHandler(QObject *o) */ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot, - QObject::QSlotObjectBase *slotObj, Qt::ConnectionType type, + QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type, const int *types, const QMetaObject *senderMetaObject) { if (!sender || !signal || !slotObj || !senderMetaObject) { qWarning("QObject::connect: invalid null parametter"); if (slotObj && !slotObj->ref.deref()) - delete slotObj; + slotObj->destroy(); return QMetaObject::Connection(); } int signal_index = -1; @@ -4200,7 +4206,7 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa if (signal_index < 0 || signal_index >= QMetaObjectPrivate::get(senderMetaObject)->signalCount) { qWarning("QObject::connect: signal not found in %s", senderMetaObject->className()); if (!slotObj->ref.deref()) - delete slotObj; + slotObj->destroy(); return QMetaObject::Connection(0); } signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject); @@ -4220,7 +4226,7 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa while (c2) { if (c2->receiver == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) { if (!slotObj->ref.deref()) - delete slotObj; + slotObj->destroy(); return QMetaObject::Connection(); } c2 = c2->nextConnectionList; @@ -4412,16 +4418,6 @@ QMetaObject::Connection::~Connection() the signal or the slot, or if the arguments do not match. */ -QObject::QSlotObjectBase::~QSlotObjectBase() -{ -} - -bool QObject::QSlotObjectBase::compare(void** ) -{ - return false; -} - - QT_END_NAMESPACE #include "moc_qobject.cpp" diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 1d2d6a6794..ee157347ea 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -246,7 +246,7 @@ public: return connectImpl(sender, reinterpret_cast<void **>(&signal), receiver, reinterpret_cast<void **>(&slot), - new QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value, + new QtPrivate::QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value, typename SignalType::ReturnType>(slot), type, types, &SignalType::Object::staticMetaObject); } @@ -268,7 +268,7 @@ public: "Return type of the slot is not compatible with the return type of the signal."); return connectImpl(sender, reinterpret_cast<void **>(&signal), sender, 0, - new QStaticSlotObject<Func2, + new QtPrivate::QStaticSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value, typename SignalType::ReturnType>(slot), Qt::DirectConnection, 0, &SignalType::Object::staticMetaObject); @@ -282,7 +282,7 @@ public: typedef QtPrivate::FunctionPointer<Func1> SignalType; return connectImpl(sender, reinterpret_cast<void **>(&signal), sender, 0, - new QFunctorSlotObject<Func2, SignalType::ArgumentCount, typename SignalType::Arguments, typename SignalType::ReturnType>(slot), + new QtPrivate::QFunctorSlotObject<Func2, SignalType::ArgumentCount, typename SignalType::Arguments, typename SignalType::ReturnType>(slot), Qt::DirectConnection, 0, &SignalType::Object::staticMetaObject); } #endif //Q_QDOC @@ -394,56 +394,10 @@ private: Q_DISABLE_COPY(QObject) Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *)) - private: - // internal base class (interface) containing functions required to call a slot managed by a pointer to function. - struct Q_CORE_EXPORT QSlotObjectBase { - QAtomicInt ref; - QSlotObjectBase() : ref(1) {} - virtual ~QSlotObjectBase(); - virtual void call(QObject *receiver, void **a) = 0; - virtual bool compare(void **); - }; - // implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject - // Args and R are the List of arguments and the returntype of the signal to which the slot is connected. - template<typename Func, typename Args, typename R> struct QSlotObject : QSlotObjectBase - { - typedef QtPrivate::FunctionPointer<Func> FuncType; - Func function; - QSlotObject(Func f) : function(f) {} - virtual void call(QObject *receiver, void **a) { - FuncType::template call<Args, R>(function, static_cast<typename FuncType::Object *>(receiver), a); - } - virtual bool compare(void **f) { - return *reinterpret_cast<Func *>(f) == function; - } - }; - // implementation of QSlotObjectBase for which the slot is a static function - // Args and R are the List of arguments and the returntype of the signal to which the slot is connected. - template<typename Func, typename Args, typename R> struct QStaticSlotObject : QSlotObjectBase - { - typedef QtPrivate::FunctionPointer<Func> FuncType; - Func function; - QStaticSlotObject(Func f) : function(f) {} - virtual void call(QObject *receiver, void **a) { - FuncType::template call<Args, R>(function, receiver, a); - } - }; - // implementation of QSlotObjectBase for which the slot is a functor (or lambda) - // N is the number of arguments - // Args and R are the List of arguments and the returntype of the signal to which the slot is connected. - template<typename Func, int N, typename Args, typename R> struct QFunctorSlotObject : QSlotObjectBase - { - typedef QtPrivate::Functor<Func, N> FuncType; - Func function; - QFunctorSlotObject(const Func &f) : function(f) {} - virtual void call(QObject *receiver, void **a) { - FuncType::template call<Args, R>(function, receiver, a); - } - }; - +private: static QMetaObject::Connection connectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slotPtr, - QSlotObjectBase *slot, Qt::ConnectionType type, + QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, const int *types, const QMetaObject *senderMetaObject); static bool disconnectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot, diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index e016002afa..eeb64db0dd 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -99,6 +99,104 @@ namespace QtPrivate { 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 + + // internal base class (interface) containing functions required to call a slot managed by a pointer to function. + struct QSlotObjectBase { + QAtomicInt ref; + // don't use virtual functions here; we don't want the + // compiler to create tons of per-polymorphic-class stuff that + // we'll never need. We just use one function pointer. + enum Operation { + Destroy, + Call, + Compare, + + NumOperations + }; + typedef bool (*ImplFn)(int which, QSlotObjectBase* this_, QObject *receiver, void **args); + const ImplFn impl; + + explicit QSlotObjectBase(ImplFn fn) : ref(1), impl(fn) {} // ### make constexpr once QAtomicInt's ctor is, too + inline void destroy() { impl(Destroy, this, 0, 0); } + inline bool compare(void **a) { return impl(Compare, this, 0, a); } + inline void call(QObject *r, void **a) { impl(Call, this, r, a); } + protected: + ~QSlotObjectBase() {} + }; + // implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject + // Args and R are the List of arguments and the returntype of the signal to which the slot is connected. + template<typename Func, typename Args, typename R> class QSlotObject : public QSlotObjectBase + { + typedef QtPrivate::FunctionPointer<Func> FuncType; + Func function; + static bool impl(int which, QSlotObjectBase *this_, QObject *r, void **a) + { + switch (which) { + case Destroy: + delete static_cast<QSlotObject*>(this_); + return true; + case Call: + FuncType::template call<Args, R>(static_cast<QSlotObject*>(this_)->function, static_cast<typename FuncType::Object *>(r), a); + return true; + case Compare: + return *reinterpret_cast<Func *>(a) == static_cast<QSlotObject*>(this_)->function; + case NumOperations: ; + } + return false; + } + public: + explicit QSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {} + }; + // implementation of QSlotObjectBase for which the slot is a static function + // Args and R are the List of arguments and the returntype of the signal to which the slot is connected. + template<typename Func, typename Args, typename R> class QStaticSlotObject : public QSlotObjectBase + { + typedef QtPrivate::FunctionPointer<Func> FuncType; + Func function; + static bool impl(int which, QSlotObjectBase *this_, QObject *r, void **a) + { + switch (which) { + case Destroy: + delete static_cast<QStaticSlotObject*>(this_); + return true; + case Call: + FuncType::template call<Args, R>(static_cast<QStaticSlotObject*>(this_)->function, r, a); + return true; + case Compare: + return false; // not implemented + case NumOperations: ; + } + return false; + } + public: + explicit QStaticSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {} + }; + // implementation of QSlotObjectBase for which the slot is a functor (or lambda) + // N is the number of arguments + // Args and R are the List of arguments and the returntype of the signal to which the slot is connected. + template<typename Func, int N, typename Args, typename R> class QFunctorSlotObject : public QSlotObjectBase + { + typedef QtPrivate::Functor<Func, N> FuncType; + Func function; + static bool impl(int which, QSlotObjectBase *this_, QObject *r, void **a) + { + switch (which) { + case Destroy: + delete static_cast<QFunctorSlotObject*>(this_); + return true; + case Call: + FuncType::template call<Args, R>(static_cast<QFunctorSlotObject*>(this_)->function, r, a); + return true; + case Compare: + return false; // not implemented + case NumOperations: ; + } + return false; + } + public: + explicit QFunctorSlotObject(const Func &f) : QSlotObjectBase(&impl), function(f) {} + }; + } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 02580caf41..d47426b14c 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -120,7 +120,7 @@ public: QObject *receiver; union { StaticMetaCallFunction callFunction; - QObject::QSlotObjectBase *slotObj; + QtPrivate::QSlotObjectBase *slotObj; }; // The next pointer for the singly-linked ConnectionList Connection *nextConnectionList; @@ -280,7 +280,7 @@ public: /*! \internal \a signalId is in the signal index range (see QObjectPrivate::signalIndex()). */ - QMetaCallEvent(QObject::QSlotObjectBase *slotObj, const QObject *sender, int signalId, + QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, int signalId, int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0); ~QMetaCallEvent(); @@ -293,7 +293,7 @@ public: virtual void placeMetaCall(QObject *object); private: - QObject::QSlotObjectBase *slotObj_; + QtPrivate::QSlotObjectBase *slotObj_; const QObject *sender_; int signalId_; int nargs_; |