QDeadlineTimer: make it so any negative millisecond count is "forever"

We have quite a few Qt API that assumes this, so making this change
helps transitioning them to QDeadlineTimer.

[ChangeLog][Important Behavior Changes] QDeadlineTimer will now
interpret negative millisecond remaining times as "forever", instead of
only the value -1. This brings the API closer in line with other API
like QMutex. This change does not apply to the nanosecond counts in the
API, nor to the API based on std::chrono.

Change-Id: I6f518d59e63249ddbf43fffd175a3e5bead564ae
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Thiago Macieira 2023-04-28 16:52:55 -07:00
parent d848e6d87d
commit ec0e0d1e81
2 changed files with 43 additions and 11 deletions

View File

@ -164,7 +164,7 @@ static qint64 add_saturate(qint64 t1, Duration1 dur, Durations... extra)
from the moment of the creation of this object, if msecs is positive. If \a
msecs is zero, this QDeadlineTimer will be marked as expired, causing
remainingTime() to return zero and deadline() to return an indeterminate
time point in the past. If \a msecs is -1, the timer will be set to never
time point in the past. If \a msecs is negative, the timer will be set to never
expire, causing remainingTime() to return -1 and deadline() to return the
maximum value.
@ -177,6 +177,9 @@ static qint64 add_saturate(qint64 t1, Duration1 dur, Durations... extra)
functionality is required, use QDeadlineTimer::current() and add time to
it.
\note Prior to Qt 6.6, the only value that caused the timer to never expire
was -1.
\sa hasExpired(), isForever(), remainingTime(), setRemainingTime()
*/
QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) noexcept
@ -243,16 +246,19 @@ QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) noexcept
/*!
Sets the remaining time for this QDeadlineTimer object to \a msecs
milliseconds from now, if \a msecs has a positive value. If \a msecs is
zero, this QDeadlineTimer object will be marked as expired, whereas a value
of -1 will set it to never expire.
zero, this QDeadlineTimer object will be marked as expired, whereas a
negative value will set it to never expire.
The timer type for this QDeadlineTimer object will be set to the specified \a timerType.
\note Prior to Qt 6.6, the only value that caused the timer to never expire
was -1.
\sa setPreciseRemainingTime(), hasExpired(), isForever(), remainingTime()
*/
void QDeadlineTimer::setRemainingTime(qint64 msecs, Qt::TimerType timerType) noexcept
{
if (msecs == -1) {
if (msecs < 0) {
*this = QDeadlineTimer(Forever, timerType);
return;
}
@ -266,17 +272,21 @@ void QDeadlineTimer::setRemainingTime(qint64 msecs, Qt::TimerType timerType) noe
/*!
Sets the remaining time for this QDeadlineTimer object to \a secs seconds
plus \a nsecs nanoseconds from now, if \a secs has a positive value. If \a
secs is -1, this QDeadlineTimer will be set it to never expire. If both
parameters are zero, this QDeadlineTimer will be marked as expired.
secs is negative, this QDeadlineTimer will be set it to never expire (this
behavior does not apply to \a nsecs). If both parameters are zero, this
QDeadlineTimer will be marked as expired.
The timer type for this QDeadlineTimer object will be set to the specified
\a timerType.
\note Prior to Qt 6.6, the only condition that caused the timer to never
expire was when \a secs was -1.
\sa setRemainingTime(), hasExpired(), isForever(), remainingTime()
*/
void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::TimerType timerType) noexcept
{
if (secs == -1) {
if (secs < 0) {
*this = QDeadlineTimer(Forever, timerType);
return;
}

View File

@ -458,17 +458,39 @@ void tst_QDeadlineTimer::overflow()
// Make sure setRemainingTime underflows gracefully
deadline.setPreciseRemainingTime(std::numeric_limits<qint64>::min() / 10, 0, timerType);
QVERIFY(!deadline.isForever()); // The above underflows, so make sure we don't saturate to Forever
QCOMPARE(deadline.remainingTimeNSecs(), 0);
QVERIFY(deadline.remainingTime() == 0);
QVERIFY(deadline.isForever()); // The above could underflow, so make sure we did set to Forever
QCOMPARE(deadline.remainingTimeNSecs(), -1);
QCOMPARE(deadline.remainingTime(), -1);
// If the timer is saturated we don't want to get a valid number of milliseconds
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::min());
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
// Check that the conversion to milliseconds and nanoseconds underflows gracefully
deadline.setPreciseDeadline(std::numeric_limits<qint64>::min() / 10, 0, timerType);
QVERIFY(!deadline.isForever()); // The above underflows, make sure we don't saturate to Forever
QVERIFY(deadline.deadline() == std::numeric_limits<qint64>::min());
QVERIFY(deadline.deadlineNSecs() == std::numeric_limits<qint64>::min());
// Check that subtracting max() twice doesn't make it become positive
deadline.setPreciseDeadline(0);
deadline -= std::numeric_limits<qint64>::max();
deadline -= std::numeric_limits<qint64>::max();
QVERIFY(!deadline.isForever());
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::min());
QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::min());
// Ditto for adding max()
deadline.setPreciseDeadline(0);
deadline += std::numeric_limits<qint64>::max();
deadline += std::numeric_limits<qint64>::max();
QVERIFY(deadline.isForever()); // it's so far in the future it's effectively forever
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
// But we don't un-become forever after saturation
deadline -= std::numeric_limits<qint64>::max();
QVERIFY(deadline.isForever());
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
}
void tst_QDeadlineTimer::expire()