From 6991e848e3a0470e301d006a799b1351909884ca Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 28 Aug 2024 15:44:39 +0200 Subject: [PATCH] QTimer: make singleShot() have nanoseconds resolution [2/2]: new-style Port the new-style singleShot() static methods from milliseconds to nanoseconds resolution. This matches what QChronoTimer provides, but we want to minimize porting for users come Qt 7, so we don't want users to first have to port to QChronoTimer::singleShot() and then back to QTimer::singleShot(); we want them to continue to use QTimer. The only reason QChronoTimer is a separate class from QTimer is that the latter has an int interval property and we can't just port it to milli- or nanoseconds chrono types if we want users to actually access the extra range or precision afforded by the chrono types. But that's not an issue for the singleShot() static methods, as they never return an object that could be asked for its timeout. The old-style static methods were already ported in the first step, which also contain the ChangeLog common to both patches. Pick-to: 6.8 Task-number: QTBUG-128426 Change-Id: I1899465c3b852ab546983a0bf35853fdd3f91ef3 Reviewed-by: Thiago Macieira --- src/corelib/compat/removed_api.cpp | 8 ++++++++ src/corelib/kernel/qtimer.cpp | 23 ++++++++++++++--------- src/corelib/kernel/qtimer.h | 4 ++++ 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp index be61de4611a..827bed9bf74 100644 --- a/src/corelib/compat/removed_api.cpp +++ b/src/corelib/compat/removed_api.cpp @@ -1174,6 +1174,14 @@ void QTimer::singleShot(std::chrono::milliseconds interval, Qt::TimerType timerT singleShot(from_msecs(interval), timerType, receiver, member); } +void QTimer::singleShotImpl(std::chrono::milliseconds interval, Qt::TimerType timerType, + const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj) +{ + QtPrivate::SlotObjUniquePtr slot(slotObj); // don't leak if from_msecs throws + const auto ns = from_msecs(interval); + singleShotImpl(ns, timerType, receiver, slot.release()); +} + #include "qurl.h" bool QUrl::operator<(const QUrl &url) const diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 3a9571a9d85..9b23cc28fb2 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -319,11 +319,11 @@ QTimer::from_msecs(std::chrono::milliseconds ms) as the final sender class. \a slotObj the slot object */ -void QTimer::singleShotImpl(std::chrono::milliseconds msec, Qt::TimerType timerType, +void QTimer::singleShotImpl(std::chrono::nanoseconds ns, Qt::TimerType timerType, const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj) { - if (msec == 0ms) { + if (ns == 0ns) { 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. @@ -352,7 +352,7 @@ void QTimer::singleShotImpl(std::chrono::milliseconds msec, Qt::TimerType timerT return; } - new QSingleShotTimer(from_msecs(msec), timerType, receiver, slotObj); + (void) new QSingleShotTimer(ns, timerType, receiver, slotObj); } /*! @@ -420,14 +420,14 @@ void QTimer::singleShot(std::chrono::nanoseconds ns, Qt::TimerType timerType, } } -/*! \fn template void QTimer::singleShot(Duration msec, const QObject *context, Functor &&functor) - \fn template void QTimer::singleShot(Duration msec, Qt::TimerType timerType, const QObject *context, Functor &&functor) - \fn template void QTimer::singleShot(Duration msec, Functor &&functor) - \fn template void QTimer::singleShot(Duration msec, Qt::TimerType timerType, Functor &&functor) +/*! \fn template void QTimer::singleShot(Duration interval, const QObject *context, Functor &&functor) + \fn template void QTimer::singleShot(Duration interval, Qt::TimerType timerType, const QObject *context, Functor &&functor) + \fn template void QTimer::singleShot(Duration interval, Functor &&functor) + \fn template void QTimer::singleShot(Duration interval, Qt::TimerType timerType, Functor &&functor) \since 5.4 \reentrant - This static function calls \a functor after \a msec milliseconds. + This static function calls \a functor after \a interval. It is very convenient to use this function because you do not need to bother with a \l{QObject::timerEvent()}{timerEvent} or @@ -441,7 +441,12 @@ void QTimer::singleShot(std::chrono::nanoseconds ns, Qt::TimerType timerType, If \a functor is a member function of \a context, then the function will be called on the object. - The \a msec parameter can be an \c int or a \c std::chrono::milliseconds value. + The \a interval parameter can be an \c int (interpreted as a millisecond + count) or a \c std::chrono type that implicitly converts to nanoseconds. + + \note In Qt versions prior to 6.8, the chrono overloads took chrono::milliseconds, + not chrono::nanoseconds. The compiler will automatically convert for you, + but the conversion may overflow for extremely large milliseconds counts. \sa start() */ diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h index 2403b963487..0faaab5f601 100644 --- a/src/corelib/kernel/qtimer.h +++ b/src/corelib/kernel/qtimer.h @@ -173,8 +173,12 @@ private: static void singleShotImpl(int msec, Qt::TimerType timerType, const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj); +#if QT_CORE_REMOVED_SINCE(6, 8) static void singleShotImpl(std::chrono::milliseconds interval, Qt::TimerType timerType, const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj); +#endif + static void singleShotImpl(std::chrono::nanoseconds interval, Qt::TimerType timerType, + const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj); }; #if QT_CORE_INLINE_IMPL_SINCE(6, 8)