diff options
| author | Ahmad Samir <a.samirh78@gmail.com> | 2024-12-19 14:10:31 +0200 |
|---|---|---|
| committer | Ahmad Samir <a.samirh78@gmail.com> | 2025-02-10 01:13:29 +0200 |
| commit | f1f610bc67bfd5c2ef31270a6945e7bae93b5e4a (patch) | |
| tree | 95df313ad5a5a6bd79501073a6f7311a257d1a1b /src/corelib/kernel/qtimer.cpp | |
| parent | d4c312f68aee526848b7b2f0e4b77948e8b55e8f (diff) | |
Qt Timers: disallow setting negative intervals
As disccussed in the code review. Replace negative values with 1ms (not
0ms as that would spin up the event-loop too many times).
Move QTimer::start(std::chrono::milliseconds msec) API docs next to the
method definition so as to not forget changing it when the
implementation changes.
Drive-by, qWarning() and co. are marked cold so there is no need to use
Q_UNLIKELY in an if-condition leading to calling these methods.
[ChangeLog][QtCore][Important Behvaior Change] Timers with negative
intervals aren't allowed anymore, that is, if you try to start a timer
(or set the interval) with a negative value, that interval will be set
to 1ms. Previously Qt timers would let you set the interval to a
negative value, but behave in surprising ways (for example stop the
timer if it was running or not start it at all). This change affects
QTimer, QChronoTimer, QBasicTimer and QObject::startTimer().
Fixes: QTBUG-132359
Change-Id: I09309063665db051337f91160971993d9ce7911e
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel/qtimer.cpp')
| -rw-r--r-- | src/corelib/kernel/qtimer.cpp | 72 |
1 files changed, 52 insertions, 20 deletions
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index e3b4b0ec36d..796a82afe0b 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -233,6 +233,8 @@ void QTimer::start() timer.start(); \endcode + \include timers-common.qdocinc negative-intervals-not-allowed + \note Keeping the event loop busy with a zero-timer is bound to cause trouble and highly erratic behavior of the UI. */ @@ -241,9 +243,40 @@ void QTimer::start(int msec) start(msec * 1ms); } +static std::chrono::milliseconds +checkInterval(const char *caller, std::chrono::milliseconds interval) +{ + if (interval < 0ms) { + qWarning("%s: negative intervals aren't allowed; the interval will be set to 1ms.", caller); + interval = 1ms; + } + return interval; +} + +/*! + \since 5.8 + \overload + + Starts or restarts the timer with a timeout of duration \a interval milliseconds. + + \include qtimer.cpp stop-restart-timer + + \include qtimer.cpp singleshot-activation + This is equivalent to: + + \code + timer.setInterval(interval); + timer.start(); + \endcode + + \include timers-common.qdocinc negative-intervals-not-allowed +*/ void QTimer::start(std::chrono::milliseconds interval) { Q_D(QTimer); + + interval = checkInterval("QTimer::start", interval); + // This could be narrowing as the interval is stored in an `int` QProperty, // and the type can't be changed in Qt6. const int msec = interval.count(); @@ -370,6 +403,8 @@ void QTimer::singleShotImpl(std::chrono::nanoseconds ns, Qt::TimerType timerType The \a receiver is the receiving object and the \a member is the slot. The time interval is \a msec milliseconds. + \include timers-common.qdocinc negative-intervals-not-allowed + \sa start() */ @@ -388,6 +423,8 @@ void QTimer::singleShotImpl(std::chrono::nanoseconds ns, Qt::TimerType timerType time interval is \a msec milliseconds. The \a timerType affects the accuracy of the timer. + \include timers-common.qdocinc negative-intervals-not-allowed + \sa start() */ @@ -395,8 +432,9 @@ void QTimer::singleShot(std::chrono::nanoseconds ns, Qt::TimerType timerType, const QObject *receiver, const char *member) { if (ns < 0ns) { - qWarning("QTimer::singleShot: Timers cannot have negative timeouts"); - return; + qWarning("QTimer::singleShot: negative intervals aren't allowed; the " + "interval will be set to 1ms."); + ns = 1ms; } if (receiver && member) { if (ns == 0ns) { @@ -440,6 +478,8 @@ void QTimer::singleShot(std::chrono::nanoseconds ns, Qt::TimerType timerType, 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. + \include timers-common.qdocinc negative-intervals-not-allowed + \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. @@ -462,6 +502,8 @@ void QTimer::singleShot(std::chrono::nanoseconds ns, Qt::TimerType timerType, The \a receiver is the receiving object and the \a member is the slot. The time interval is given in the duration object \a nsec. + \include timers-common.qdocinc negative-intervals-not-allowed + //! [qtimer-ns-overflow] \note In Qt versions prior to 6.8, this function took chrono::milliseconds, not chrono::nanoseconds. The compiler will automatically convert for you, @@ -487,6 +529,9 @@ void QTimer::singleShot(std::chrono::nanoseconds ns, Qt::TimerType timerType, time interval is given in the duration object \a nsec. The \a timerType affects the accuracy of the timer. + + \include timers-common.qdocinc negative-intervals-not-allowed + \include qtimer.cpp qtimer-ns-overflow \sa start() @@ -527,24 +572,6 @@ void QTimer::singleShot(std::chrono::nanoseconds ns, Qt::TimerType timerType, */ /*! - \fn void QTimer::start(std::chrono::milliseconds msec) - \since 5.8 - \overload - - Starts or restarts the timer with a timeout of duration \a msec milliseconds. - - \include qtimer.cpp stop-restart-timer - - \include qtimer.cpp singleshot-activation - This is equivalent to: - - \code - timer.setInterval(msec); - timer.start(); - \endcode -*/ - -/*! \fn std::chrono::milliseconds QTimer::intervalAsDuration() const \since 5.8 @@ -604,6 +631,8 @@ QBindable<bool> QTimer::bindableSingleShot() stop() and then start() the timer, and acquire a new id(). If the timer is not running, only the interval is changed. + \include timers-common.qdocinc negative-intervals-not-allowed + \sa singleShot */ void QTimer::setInterval(int msec) @@ -614,6 +643,9 @@ void QTimer::setInterval(int msec) void QTimer::setInterval(std::chrono::milliseconds interval) { Q_D(QTimer); + + interval = checkInterval("QTimer::setInterval", interval); + // This could be narrowing as the interval is stored in an `int` QProperty, // and the type can't be changed in Qt6. const int msec = interval.count(); |
