diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2013-11-26 10:51:33 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2013-11-26 10:51:34 +0100 |
commit | 3061dc4abdfbd1a536918935d380872de6655521 (patch) | |
tree | ff440ed0c7d5816cc7e2874f73fdabfb0bce493f /src/corelib/kernel | |
parent | 25b2b682d616dd52c3515f443e3d25fc0224f3a2 (diff) | |
parent | 9b8570c4e9359eb8b45b39c28aa9d8c140f3fc44 (diff) |
Merge remote-tracking branch 'origin/release' into stable
Change-Id: I83ff8f4d7dffd7385013a1bd8a1732a89ee20d56
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/kernel.pri | 3 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_mac_objc.mm | 30 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_mac_p.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 43 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_impl.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 1 |
6 files changed, 70 insertions, 13 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 26ad9f488c..7625a74381 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -98,6 +98,9 @@ mac:!nacl { kernel/qcore_mac.cpp OBJECTIVE_SOURCES += \ kernel/qcore_mac_objc.mm + + # We need UIKit for UIDevice + ios: LIBS_PRIVATE += -framework UIKit } nacl { diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 7b9eb67969..73f8296021 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -41,6 +41,10 @@ #include <private/qcore_mac_p.h> +#ifdef Q_OS_IOS +#import <UIKit/UIKit.h> +#endif + QT_BEGIN_NAMESPACE NSString *QCFString::toNSString(const QString &string) @@ -54,5 +58,31 @@ QString QCFString::toQString(const NSString *nsstr) return toQString(reinterpret_cast<CFStringRef>(nsstr)); } +#ifdef Q_OS_IOS +QSysInfo::MacVersion qt_ios_version() +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + int major = 0, minor = 0; + NSArray *components = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."]; + switch ([components count]) { + case 3: + // We don't care about the patch version + case 2: + minor = [[components objectAtIndex:1] intValue]; + // fall through + case 1: + major = [[components objectAtIndex:0] intValue]; + break; + default: + Q_UNREACHABLE(); + } + + [pool release]; + + return QSysInfo::MacVersion(Q_MV_IOS(major, minor)); +} +#endif + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index fa911fb967..f491be9768 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -143,6 +143,10 @@ private: QString string; }; +#ifdef Q_OS_IOS +QSysInfo::MacVersion qt_ios_version(); +#endif + QT_END_NAMESPACE #endif // QCORE_MAC_P_H diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 6fb22054cc..e02026ca4c 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -177,6 +178,7 @@ private: void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; +void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = 0; int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = 0; @@ -805,8 +807,12 @@ QObject::~QObject() } } - if (d->declarativeData) - QAbstractDeclarativeData::destroyed(d->declarativeData, this); + if (d->declarativeData) { + if (QAbstractDeclarativeData::destroyed) + QAbstractDeclarativeData::destroyed(d->declarativeData, this); + if (QAbstractDeclarativeData::destroyed_qml1) + QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this); + } // set ref to zero to indicate that this object has been deleted if (d->currentSender != 0) @@ -847,9 +853,9 @@ QObject::~QObject() // The destroy operation must happen outside the lock if (c->isSlotObject) { + c->isSlotObject = false; locker.unlock(); c->slotObj->destroyIfLastRef(); - c->isSlotObject = false; locker.relock(); } c->deref(); @@ -864,15 +870,29 @@ QObject::~QObject() d->connectionLists = 0; } - // disconnect all senders + /* Disconnect all senders: + * This loop basically just does + * for (node = d->senders; node; node = node->next) { ... } + * + * We need to temporarily unlock the receiver mutex to destroy the functors or to lock the + * sender's mutex. And when the mutex is released, node->next might be destroyed by another + * thread. That's why we set node->prev to &node, that way, if node is destroyed, node will + * be updated. + */ QObjectPrivate::Connection *node = d->senders; while (node) { QObject *sender = node->sender; + // Send disconnectNotify before removing the connection from sender's connection list. + // This ensures any eventual destructor of sender will block on getting receiver's lock + // and not finish until we release it. + sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index)); QMutex *m = signalSlotLock(sender); node->prev = &node; bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? if (!node || node->sender != sender) { + // We hold the wrong mutex + Q_ASSERT(needToUnlock); m->unlock(); continue; } @@ -881,8 +901,6 @@ QObject::~QObject() if (senderLists) senderLists->dirty = true; - int signal_index = node->signal_index; - QtPrivate::QSlotObjectBase *slotObj = Q_NULLPTR; if (node->isSlotObject) { slotObj = node->slotObj; @@ -894,12 +912,12 @@ QObject::~QObject() m->unlock(); if (slotObj) { + if (node) + node->prev = &node; locker.unlock(); slotObj->destroyIfLastRef(); locker.relock(); } - - sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), signal_index)); } } @@ -1858,7 +1876,7 @@ void QObjectPrivate::setParent_helper(QObject *o) } } } - if (!isDeletingChildren && declarativeData) + if (!isDeletingChildren && declarativeData && QAbstractDeclarativeData::parentChanged) QAbstractDeclarativeData::parentChanged(declarativeData, q, o); } @@ -3163,7 +3181,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, && (slot == 0 || (c->isSlotObject && c->slotObj->compare(slot)))))) { bool needToUnlock = false; QMutex *receiverMutex = 0; - if (!receiver) { + if (c->receiver) { receiverMutex = signalSlotLock(c->receiver); // need to relock this receiver and sender in the correct order needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex); @@ -3180,9 +3198,9 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, c->receiver = 0; if (c->isSlotObject) { + c->isSlotObject = false; senderMutex->unlock(); c->slotObj->destroyIfLastRef(); - c->isSlotObject = false; senderMutex->lock(); } @@ -3211,8 +3229,7 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, QObject *s = const_cast<QObject *>(sender); QMutex *senderMutex = signalSlotLock(sender); - QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0; - QOrderedMutexLocker locker(senderMutex, receiverMutex); + QMutexLocker locker(senderMutex); QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; if (!connectionLists) diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index 1bbd548be6..d2996e6e4d 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -99,6 +99,8 @@ namespace QtPrivate { template <typename ArgList, bool Declared = TypesAreDeclaredMetaType<ArgList>::Value > struct ConnectionTypes { static const int *types() { return 0; } }; + template <> struct ConnectionTypes<List<>, true> + { 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 diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index f5745515c9..cd2d592cec 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -90,6 +90,7 @@ class Q_CORE_EXPORT QAbstractDeclarativeData { public: static void (*destroyed)(QAbstractDeclarativeData *, QObject *); + static void (*destroyed_qml1)(QAbstractDeclarativeData *, QObject *); static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *); static void (*signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **); static int (*receivers)(QAbstractDeclarativeData *, const QObject *, int); |