diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/corelib/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/corelib/kernel/qsingleshottimer_p.h | 119 | ||||
| -rw-r--r-- | src/corelib/kernel/qtimer.cpp | 86 |
3 files changed, 121 insertions, 85 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index b19dc8ec82e..9cf67be32fb 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -181,6 +181,7 @@ qt_internal_add_module(Core kernel/qsocketnotifier.cpp kernel/qsocketnotifier.h kernel/qsystemerror.cpp kernel/qsystemerror_p.h kernel/qtestsupport_core.cpp kernel/qtestsupport_core.h + kernel/qsingleshottimer_p.h kernel/qtimer.cpp kernel/qtimer.h kernel/qtimer_p.h kernel/qtranslator.cpp kernel/qtranslator.h kernel/qtranslator_p.h kernel/qvariant.cpp kernel/qvariant.h kernel/qvariant_p.h diff --git a/src/corelib/kernel/qsingleshottimer_p.h b/src/corelib/kernel/qsingleshottimer_p.h new file mode 100644 index 00000000000..636f209ea17 --- /dev/null +++ b/src/corelib/kernel/qsingleshottimer_p.h @@ -0,0 +1,119 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QSINGLESHOTTIMER_P_H +#define QSINGLESHOTTIMER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qabstracteventdispatcher.h" +#include "qcoreapplication.h" +#include "qmetaobject_p.h" + +QT_BEGIN_NAMESPACE + +class QSingleShotTimer : public QObject +{ + Q_OBJECT + int timerId = -1; + +public: + inline ~QSingleShotTimer(); + inline QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, + const char *member); + inline QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, + QtPrivate::QSlotObjectBase *slotObj); + + inline void startTimerForReceiver(int msec, Qt::TimerType timerType, const QObject *receiver); + +Q_SIGNALS: + void timeout(); + +protected: + inline void timerEvent(QTimerEvent *) override; +}; + +QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, + const char *member) + : QObject(QAbstractEventDispatcher::instance()) +{ + connect(this, SIGNAL(timeout()), r, member); + + startTimerForReceiver(msec, timerType, r); +} + +QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, + QtPrivate::QSlotObjectBase *slotObj) + : QObject(QAbstractEventDispatcher::instance()) +{ + int signal_index = QMetaObjectPrivate::signalOffset(&staticMetaObject); + Q_ASSERT(QMetaObjectPrivate::signal(&staticMetaObject, signal_index).name() == "timeout"); + QObjectPrivate::connectImpl(this, signal_index, r ? r : this, nullptr, slotObj, + Qt::AutoConnection, nullptr, &staticMetaObject); + + startTimerForReceiver(msec, timerType, r); +} + +QSingleShotTimer::~QSingleShotTimer() +{ + if (timerId > 0) + killTimer(timerId); +} + +/* + Move the timer, and the dispatching and handling of the timer event, into + the same thread as where it will be handled, so that it fires reliably even + if the thread that set up the timer is busy. +*/ +void QSingleShotTimer::startTimerForReceiver(int msec, Qt::TimerType timerType, + const QObject *receiver) +{ + if (receiver && receiver->thread() != thread()) { + // Avoid leaking the QSingleShotTimer instance in case the application exits before the + // timer fires + connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, + &QObject::deleteLater); + setParent(nullptr); + moveToThread(receiver->thread()); + + QDeadlineTimer deadline(std::chrono::milliseconds{msec}, timerType); + QMetaObject::invokeMethod(this, [this, deadline, timerType] { + if (deadline.hasExpired()) + emit timeout(); + else + timerId = startTimer(std::chrono::milliseconds{deadline.remainingTime()}, timerType); + }, Qt::QueuedConnection); + } else { + timerId = startTimer(std::chrono::milliseconds{msec}, timerType); + } +} + +void QSingleShotTimer::timerEvent(QTimerEvent *) +{ + // need to kill the timer _before_ we emit timeout() in case the + // slot connected to timeout calls processEvents() + if (timerId > 0) + killTimer(timerId); + timerId = -1; + + emit timeout(); + + // we would like to use delete later here, but it feels like a + // waste to post a new event to handle this event, so we just unset the flag + // and explicitly delete... + qDeleteInEventHandler(this); +} + +QT_END_NAMESPACE + +#endif // qsingleshottimer_p.h diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index c591b0ecec3..19e80ca6730 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -4,6 +4,7 @@ #include "qtimer.h" #include "qtimer_p.h" +#include "qsingleshottimer_p.h" #include "qabstracteventdispatcher.h" #include "qcoreapplication.h" @@ -253,90 +254,6 @@ void QTimer::timerEvent(QTimerEvent *e) } } -class QSingleShotTimer : public QObject -{ - Q_OBJECT - int timerId = -1; -public: - ~QSingleShotTimer(); - QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char * m); - QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj); - - void startTimerForReceiver(int msec, Qt::TimerType timerType, const QObject *receiver); - -Q_SIGNALS: - void timeout(); -protected: - void timerEvent(QTimerEvent *) override; -}; - -QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char *member) - : QObject(QAbstractEventDispatcher::instance()) -{ - connect(this, SIGNAL(timeout()), r, member); - - startTimerForReceiver(msec, timerType, r); -} - -QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj) - : QObject(QAbstractEventDispatcher::instance()) -{ - int signal_index = QMetaObjectPrivate::signalOffset(&staticMetaObject); - Q_ASSERT(QMetaObjectPrivate::signal(&staticMetaObject, signal_index).name() == "timeout"); - QObjectPrivate::connectImpl(this, signal_index, r ? r : this, nullptr, slotObj, - Qt::AutoConnection, nullptr, &staticMetaObject); - - startTimerForReceiver(msec, timerType, r); -} - -QSingleShotTimer::~QSingleShotTimer() -{ - if (timerId > 0) - killTimer(timerId); -} - -/* - Move the timer, and the dispatching and handling of the timer event, into - the same thread as where it will be handled, so that it fires reliably even - if the thread that set up the timer is busy. -*/ -void QSingleShotTimer::startTimerForReceiver(int msec, Qt::TimerType timerType, const QObject *receiver) -{ - if (receiver && receiver->thread() != thread()) { - // Avoid leaking the QSingleShotTimer instance in case the application exits before the timer fires - connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater); - setParent(nullptr); - moveToThread(receiver->thread()); - - QDeadlineTimer deadline(std::chrono::milliseconds{msec}, timerType); - QMetaObject::invokeMethod(this, [this, deadline, timerType]{ - if (deadline.hasExpired()) - emit timeout(); - else - timerId = startTimer(std::chrono::milliseconds{deadline.remainingTime()}, timerType); - }, Qt::QueuedConnection); - } else { - timerId = startTimer(std::chrono::milliseconds{msec}, timerType); - } -} - - -void QSingleShotTimer::timerEvent(QTimerEvent *) -{ - // need to kill the timer _before_ we emit timeout() in case the - // slot connected to timeout calls processEvents() - if (timerId > 0) - killTimer(timerId); - timerId = -1; - - emit timeout(); - - // we would like to use delete later here, but it feels like a - // waste to post a new event to handle this event, so we just unset the flag - // and explicitly delete... - qDeleteInEventHandler(this); -} - /*! \internal @@ -699,5 +616,4 @@ QBindable<Qt::TimerType> QTimer::bindableTimerType() QT_END_NAMESPACE -#include "qtimer.moc" #include "moc_qtimer.cpp" |
