diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qobjectdefs.h | 1 | ||||
-rw-r--r-- | src/corelib/kernel/qtimer.cpp | 29 | ||||
-rw-r--r-- | src/testlib/qtest.h | 27 |
3 files changed, 42 insertions, 15 deletions
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 28674193c3..418b8cf1d2 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -576,6 +576,7 @@ struct Q_CORE_EXPORT QMetaObject private: static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret); + friend class QTimer; }; class Q_CORE_EXPORT QMetaObject::Connection { diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 13f027074a..188d529f04 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -42,6 +42,8 @@ #include "qabstracteventdispatcher.h" #include "qcoreapplication.h" #include "qobject_p.h" +#include "qthread.h" +#include "qcoreapplication_p.h" QT_BEGIN_NAMESPACE @@ -343,6 +345,33 @@ void QTimer::singleShotImpl(int msec, Qt::TimerType timerType, const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj) { + if (msec == 0) { + bool deleteReceiver = false; + // Optimize: set a receiver context when none is given, such that we can use + // QMetaObject::invokeMethod which is more efficient than going through a timer. + // We need a QObject living in the current thread. But the QThread itself lives + // in a different thread - with the exception of the main QThread which lives in + // itself. And QThread::currentThread() is among the few QObjects we know that will + // most certainly be there. Note that one can actually call singleShot before the + // QApplication is created! + if (!receiver && QThread::currentThread() == QCoreApplicationPrivate::mainThread()) { + // reuse main thread as context object + receiver = QThread::currentThread(); + } else if (!receiver) { + // Create a receiver context object on-demand. According to the benchmarks, + // this is still more efficient than going through a timer. + receiver = new QObject; + deleteReceiver = true; + } + + QMetaObject::invokeMethodImpl(const_cast<QObject *>(receiver), slotObj, + Qt::QueuedConnection, nullptr); + + if (deleteReceiver) + const_cast<QObject *>(receiver)->deleteLater(); + return; + } + new QSingleShotTimer(msec, timerType, receiver, slotObj); } diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index ebd94939ce..89abc616d9 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -424,48 +424,45 @@ int main(int argc, char *argv[]) \ # define QTEST_DISABLE_KEYPAD_NAVIGATION #endif -#define QTEST_MAIN(TestObject) \ -int main(int argc, char *argv[]) \ -{ \ +#define QTEST_MAIN_IMPL(TestObject) \ TESTLIB_SELFCOVERAGE_START(#TestObject) \ QApplication app(argc, argv); \ app.setAttribute(Qt::AA_Use96Dpi, true); \ QTEST_DISABLE_KEYPAD_NAVIGATION \ TestObject tc; \ QTEST_SET_MAIN_SOURCE_PATH \ - return QTest::qExec(&tc, argc, argv); \ -} + return QTest::qExec(&tc, argc, argv); #elif defined(QT_GUI_LIB) #include <QtTest/qtest_gui.h> -#define QTEST_MAIN(TestObject) \ -int main(int argc, char *argv[]) \ -{ \ +#define QTEST_MAIN_IMPL(TestObject) \ TESTLIB_SELFCOVERAGE_START(#TestObject) \ QGuiApplication app(argc, argv); \ app.setAttribute(Qt::AA_Use96Dpi, true); \ TestObject tc; \ QTEST_SET_MAIN_SOURCE_PATH \ - return QTest::qExec(&tc, argc, argv); \ -} + return QTest::qExec(&tc, argc, argv); #else -#define QTEST_MAIN(TestObject) \ -int main(int argc, char *argv[]) \ -{ \ +#define QTEST_MAIN_IMPL(TestObject) \ TESTLIB_SELFCOVERAGE_START(#TestObject) \ QCoreApplication app(argc, argv); \ app.setAttribute(Qt::AA_Use96Dpi, true); \ TestObject tc; \ QTEST_SET_MAIN_SOURCE_PATH \ - return QTest::qExec(&tc, argc, argv); \ -} + return QTest::qExec(&tc, argc, argv); #endif // QT_GUI_LIB +#define QTEST_MAIN(TestObject) \ +int main(int argc, char *argv[]) \ +{ \ + QTEST_MAIN_IMPL(TestObject) \ +} + #define QTEST_GUILESS_MAIN(TestObject) \ int main(int argc, char *argv[]) \ { \ |