summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qobject.cpp2
-rw-r--r--tests/auto/qpointer/tst_qpointer.cpp32
2 files changed, 34 insertions, 0 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 7fe9c52..c3102ea 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -408,6 +408,8 @@ void QMetaObject::removeGuard(QObject **ptr)
if (!hash || hash->isEmpty())
return;
QMutexLocker locker(guardHashLock());
+ if (!*ptr) //check again, under the lock
+ return;
GuardHash::iterator it = hash->find(*ptr);
const GuardHash::iterator end = hash->end();
bool more = false; //if the QObject has more pointer attached to it.
diff --git a/tests/auto/qpointer/tst_qpointer.cpp b/tests/auto/qpointer/tst_qpointer.cpp
index 5a07e41..ce23764 100644
--- a/tests/auto/qpointer/tst_qpointer.cpp
+++ b/tests/auto/qpointer/tst_qpointer.cpp
@@ -73,6 +73,7 @@ private slots:
void castDuringDestruction();
void data() const;
void dataSignature() const;
+ void threadSafety();
};
tst_QPointer::tst_QPointer()
@@ -345,5 +346,36 @@ void tst_QPointer::dataSignature() const
}
}
+class TestRunnable : public QObject, public QRunnable {
+ void run() {
+ QPointer<QObject> obj1 = new QObject;
+ QPointer<QObject> obj2 = new QObject;
+ obj1->moveToThread(thread()); // this is the owner thread
+ obj1->deleteLater(); // the delete will happen in the owner thread
+ obj2->moveToThread(thread()); // this is the owner thread
+ obj2->deleteLater(); // the delete will happen in the owner thread
+ }
+};
+
+void tst_QPointer::threadSafety()
+{
+
+ QThread owner;
+ owner.start();
+
+ QThreadPool pool;
+ for (int i = 0; i < 300; i++) {
+ QPointer<TestRunnable> task = new TestRunnable;
+ task->setAutoDelete(true);
+ task->moveToThread(&owner);
+ pool.start(task);
+ }
+ pool.waitForDone();
+
+ owner.quit();
+ owner.wait();
+}
+
+
QTEST_MAIN(tst_QPointer)
#include "tst_qpointer.moc"