Long live QDeadlineTimer
It's like QElapsedTimer, but marks a time in the future instead. [ChangeLog][QtCore] Added QDeadlineTimer, a counterpart to QElapsedTimer, used to mark a time point in the future (a deadline) and determine whether such a deadline has passed. Change-Id: Ifea6e497f11a461db432ffff144921f7fbc1d1d3 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
906fc0f5e3
commit
12eacc3bab
@ -4,6 +4,8 @@ HEADERS += \
|
|||||||
kernel/qabstracteventdispatcher.h \
|
kernel/qabstracteventdispatcher.h \
|
||||||
kernel/qabstractnativeeventfilter.h \
|
kernel/qabstractnativeeventfilter.h \
|
||||||
kernel/qbasictimer.h \
|
kernel/qbasictimer.h \
|
||||||
|
kernel/qdeadlinetimer.h \
|
||||||
|
kernel/qdeadlinetimer_p.h \
|
||||||
kernel/qelapsedtimer.h \
|
kernel/qelapsedtimer.h \
|
||||||
kernel/qeventloop.h\
|
kernel/qeventloop.h\
|
||||||
kernel/qpointer.h \
|
kernel/qpointer.h \
|
||||||
@ -46,6 +48,7 @@ SOURCES += \
|
|||||||
kernel/qabstracteventdispatcher.cpp \
|
kernel/qabstracteventdispatcher.cpp \
|
||||||
kernel/qabstractnativeeventfilter.cpp \
|
kernel/qabstractnativeeventfilter.cpp \
|
||||||
kernel/qbasictimer.cpp \
|
kernel/qbasictimer.cpp \
|
||||||
|
kernel/qdeadlinetimer.cpp \
|
||||||
kernel/qelapsedtimer.cpp \
|
kernel/qelapsedtimer.cpp \
|
||||||
kernel/qeventloop.cpp \
|
kernel/qeventloop.cpp \
|
||||||
kernel/qcoreapplication.cpp \
|
kernel/qcoreapplication.cpp \
|
||||||
|
827
src/corelib/kernel/qdeadlinetimer.cpp
Normal file
827
src/corelib/kernel/qdeadlinetimer.cpp
Normal file
@ -0,0 +1,827 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 Intel Corporation.
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the QtCore module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL21$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** As a special exception, The Qt Company gives you certain additional
|
||||||
|
** rights. These rights are described in The Qt Company LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qdeadlinetimer.h"
|
||||||
|
#include "qdeadlinetimer_p.h"
|
||||||
|
#include <qpair.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64 nsecs)
|
||||||
|
{
|
||||||
|
qint64 secs = nsecs / (1000*1000*1000);
|
||||||
|
if (nsecs < 0)
|
||||||
|
--secs;
|
||||||
|
nsecs -= secs * 1000*1000*1000;
|
||||||
|
return qMakePair(secs, nsecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QDeadlineTimer
|
||||||
|
\inmodule QtCore
|
||||||
|
\brief The QDeadlineTimer class marks a deadline in the future.
|
||||||
|
\since 5.8
|
||||||
|
|
||||||
|
\reentrant
|
||||||
|
\ingroup tools
|
||||||
|
|
||||||
|
The QDeadlineTimer class is usually used to calculate future deadlines and
|
||||||
|
verify whether the deadline has expired. QDeadlineTimer can also be used
|
||||||
|
for deadlines without expiration ("forever"). It forms a counterpart to
|
||||||
|
QElapsedTimer, which calculates how much time has elapsed since
|
||||||
|
QElapsedTimer::start() was called.
|
||||||
|
|
||||||
|
QDeadlineTimer provides a more convenient API compared to
|
||||||
|
QElapsedTimer::hasExpired().
|
||||||
|
|
||||||
|
The typical use-case for the class is to create a QDeadlineTimer before the
|
||||||
|
operation in question is started, and then use remainingTime() or
|
||||||
|
hasExpired() to determine whether to continue trying the operation.
|
||||||
|
QDeadlineTimer objects can be passed to functions being called to execute
|
||||||
|
this operation so they know how long to still operate.
|
||||||
|
|
||||||
|
\code
|
||||||
|
void executeOperation(int msecs)
|
||||||
|
{
|
||||||
|
QDeadlineTimer deadline(msecs);
|
||||||
|
do {
|
||||||
|
if (readFromDevice(deadline.remainingTime())
|
||||||
|
break;
|
||||||
|
waitForReadyRead(deadline);
|
||||||
|
} while (!deadline.hasExpired());
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
Many QDeadlineTimer functions deal with time out values, which all are
|
||||||
|
measured in milliseconds. There are two special values, the same as many
|
||||||
|
other Qt functions named \c{waitFor} or similar:
|
||||||
|
|
||||||
|
\list
|
||||||
|
\o 0: no time left, expired
|
||||||
|
\o -1: infinite time left, timer never expires
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\section1 Reference Clocks
|
||||||
|
|
||||||
|
QDeadlineTimer will use the same clock as QElapsedTimer (see
|
||||||
|
QElapsedTimer::clockType() and QElapsedTimer::isMonotonic()).
|
||||||
|
|
||||||
|
\section1 Timer types
|
||||||
|
|
||||||
|
Like QTimer, QDeadlineTimer can select among different levels of coarseness
|
||||||
|
on the timers. You can select precise timing by passing Qt::PreciseTimer to
|
||||||
|
the functions that set of change the timer, or you can select coarse timing
|
||||||
|
by passing Qt::CoarseTimer. Qt::VeryCoarseTimer is currently interpreted
|
||||||
|
the same way as Qt::CoarseTimer.
|
||||||
|
|
||||||
|
This feature is dependent on support from the operating system: if the OS
|
||||||
|
does not support a coarse timer functionality, then QDeadlineTimer will
|
||||||
|
behave like Qt::PreciseTimer was passed.
|
||||||
|
|
||||||
|
QDeadlineTimer defaults to Qt::CoarseTimer because on operating systems
|
||||||
|
that do support coarse timing, making timing calls to that clock source is
|
||||||
|
often much more efficient. The level of coarseness depends on the
|
||||||
|
operating system, but should be in the order of a couple of milliseconds.
|
||||||
|
|
||||||
|
\section1 \c{std::chrono} Compatibility
|
||||||
|
|
||||||
|
QDeadlineTimer is compatible with the \c{std::chrono} API from C++11 and
|
||||||
|
can be constructed from or compared to both \c{std::chrono::duration} and
|
||||||
|
\c{std::chrono::time_point} objects. In addition, it is fully compatible
|
||||||
|
with the time literals from C++14, which allow one to write code as:
|
||||||
|
|
||||||
|
\code
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
QDeadlineTimer deadline(30s);
|
||||||
|
device->waitForReadyRead(deadline);
|
||||||
|
if (deadline.remainingTime<nanoseconds>() > 300ms)
|
||||||
|
cleanup();
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
As can be seen in the example above, QDeadlineTimer offers a templated
|
||||||
|
version of remainingTime() and deadline() that can be used to return
|
||||||
|
\c{std::chrono} objects.
|
||||||
|
|
||||||
|
Note that comparing to \c{time_point} is not as efficient as comparing to
|
||||||
|
\c{duration}, since QDeadlineTimer may need to convert from its own
|
||||||
|
internal clock source to the clock source used by the \c{time_point} object.
|
||||||
|
Also note that, due to this conversion, the deadlines will not be precise,
|
||||||
|
so the following code is not expected to compare equally:
|
||||||
|
|
||||||
|
\code
|
||||||
|
using namespace std::chrono;
|
||||||
|
auto now = steady_clock::now();
|
||||||
|
QDeadlineTimer deadline(now + 1s);
|
||||||
|
Q_ASSERT(deadline == now + 1s);
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\sa QTime, QTimer, QDeadlineTimer, Qt::TimerType
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\enum QDeadlineTimer::ForeverConstant
|
||||||
|
|
||||||
|
\value Forever Used when creating a QDeadlineTimer to indicate the
|
||||||
|
deadline should not expire
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QDeadlineTimer::QDeadlineTimer(Qt::TimerType timerType)
|
||||||
|
|
||||||
|
Constructs an expired QDeadlineTimer object. For this object,
|
||||||
|
remainingTime() will return 0.
|
||||||
|
|
||||||
|
The timer type \a timerType may be ignored, since the timer is already
|
||||||
|
expired. Similarly, for optimization purposes, this function will not
|
||||||
|
attempt to obtain the current time and will use a value known to be in the
|
||||||
|
past. Therefore, deadline() may return an unexpected value and this object
|
||||||
|
cannot be used in calculation of how long it is overdue. If that
|
||||||
|
functionality is required, use QDeadlineTimer::current().
|
||||||
|
|
||||||
|
\sa hasExpired(), remainingTime(), timerType(), current()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QDeadlineTimer::QDeadlineTimer(ForeverConstant, Qt::TimerType timerType)
|
||||||
|
|
||||||
|
Constructs a QDeadlineTimer object that never expires. For this object,
|
||||||
|
remainingTime() will return -1, deadline() will return the maximum value,
|
||||||
|
and isForever() will return true.
|
||||||
|
|
||||||
|
The timer type \a timerType may be ignored, since the timer is already
|
||||||
|
expired.
|
||||||
|
|
||||||
|
\sa hasExpired(), isForever(), remainingTime(), timerType()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs a QDeadlineTimer object with an expiry time of \a msecs msecs
|
||||||
|
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 it to
|
||||||
|
never expire, causing remainingTime() to return -1 and deadline() to return
|
||||||
|
the maximum value.
|
||||||
|
|
||||||
|
The QDeadlineTimer object will be constructed with a timer type of \a
|
||||||
|
timerType.
|
||||||
|
|
||||||
|
For optimization purposes, if \a msecs is zero, this function may skip
|
||||||
|
obtaining the current time and may instead use a value known to be in the
|
||||||
|
past. If that happens, deadline() may return an unexpected value and this
|
||||||
|
object cannot be used in calculation of how long it is overdue. If that
|
||||||
|
functionality is required, use QDeadlineTimer::current() and add time to
|
||||||
|
it.
|
||||||
|
|
||||||
|
\sa hasExpired(), isForever(), remainingTime(), setRemainingTime()
|
||||||
|
*/
|
||||||
|
QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) Q_DECL_NOTHROW
|
||||||
|
: t2(0)
|
||||||
|
{
|
||||||
|
setRemainingTime(msecs, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QDeadlineTimer::QDeadlineTimer(std::chrono::time_point<Clock, Duration> deadline, Qt::TimerType type)
|
||||||
|
|
||||||
|
Constructs a QDeadlineTimer object with a deadline at \a deadline time
|
||||||
|
point, converting from the clock source \c{Clock} to Qt's internal clock
|
||||||
|
source (see QElapsedTimer::clcokType()).
|
||||||
|
|
||||||
|
If \a deadline is in the past, this QDeadlineTimer object is set to
|
||||||
|
expired, whereas if \a deadline is equal to \c{Duration::max()}, then this
|
||||||
|
object is set to never expire.
|
||||||
|
|
||||||
|
The QDeadlineTimer object will be constructed with a timer type of \a
|
||||||
|
timerType.
|
||||||
|
|
||||||
|
\sa hasExpired(), isForever(), remainingTime<Duration>(), setDeadline()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QDeadlineTimer::QDeadlineTimer(std::chrono::duration<Rep, Period> remaining, Qt::TimerType type)
|
||||||
|
|
||||||
|
Constructs a QDeadlineTimer object with a remaining time of \a remaining.
|
||||||
|
If \a remaining is zero or negative, this QDeadlineTimer object will be
|
||||||
|
mark as expired, whereas if \a remaining is equal to \c{duration::max()},
|
||||||
|
the object will be set to never expire.
|
||||||
|
|
||||||
|
The QDeadlineTimer object will be constructed with a timer type of \a
|
||||||
|
timerType.
|
||||||
|
|
||||||
|
This constructor can be used with C++14's user-defined literals for time, such as in:
|
||||||
|
|
||||||
|
\code
|
||||||
|
using namespace std::chrono;
|
||||||
|
QDeadlineTimer deadline(250ms);
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
For optimization purposes, if \a remaining is zero or negative, this
|
||||||
|
function may skip obtaining the current time and may instead use a value
|
||||||
|
known to be in the past. If that happens, deadline() may return an
|
||||||
|
unexpected value and this object cannot be used in calculation of how long
|
||||||
|
it is overdue. If that functionality is required, use
|
||||||
|
QDeadlineTimer::current() and add time to it.
|
||||||
|
|
||||||
|
\sa hasExpired(), isForever(), remainingTime<Duration>(), setRemainingTime()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn void QDeadlineTimer::setDeadline(std::chrono::time_point<Clock, Duration> deadline, Qt::TimerType type)
|
||||||
|
|
||||||
|
Sets this QDeadlineTimer to the deadline marked by \a deadline time
|
||||||
|
point, converting from the clock source \c{Clock} to Qt's internal clock
|
||||||
|
source (see QElapsedTimer::clcokType()).
|
||||||
|
|
||||||
|
If \a deadline is in the past, this QDeadlineTimer object is set to
|
||||||
|
expired, whereas if \a deadline is equal to \c{Duration::max()}, then this
|
||||||
|
object is set to never expire.
|
||||||
|
|
||||||
|
The timer type for this QDeadlineTimer object will be set to \a timerType type.
|
||||||
|
|
||||||
|
\sa hasExpired(), isForever(), remainingTime<Duration>(),
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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.
|
||||||
|
|
||||||
|
The timer type for this QDeadlineTimer object will be set to \a timerType type.
|
||||||
|
|
||||||
|
\sa setPreciseRemainingTime(), hasExpired(), isForever(), remainingTime()
|
||||||
|
*/
|
||||||
|
void QDeadlineTimer::setRemainingTime(qint64 msecs, Qt::TimerType timerType) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
if (msecs == -1)
|
||||||
|
*this = QDeadlineTimer(Forever, timerType);
|
||||||
|
else
|
||||||
|
setPreciseRemainingTime(0, msecs * 1000 * 1000, timerType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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.
|
||||||
|
|
||||||
|
The timer type for this QDeadlineTimer object will be set to \a timerType type.
|
||||||
|
|
||||||
|
\sa setRemainingTime(), hasExpired(), isForever(), remainingTime()
|
||||||
|
*/
|
||||||
|
void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::TimerType timerType) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
if (secs == -1) {
|
||||||
|
*this = QDeadlineTimer(Forever, timerType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*this = current(timerType);
|
||||||
|
if (QDeadlineTimerNanosecondsInT2) {
|
||||||
|
t1 += secs + toSecsAndNSecs(nsecs).first;
|
||||||
|
t2 += toSecsAndNSecs(nsecs).second;
|
||||||
|
if (t2 > 1000*1000*1000) {
|
||||||
|
t2 -= 1000*1000*1000;
|
||||||
|
++t1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t1 += secs * 1000 * 1000 * 1000 + nsecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\overload
|
||||||
|
\fn void QDeadlineTimer::setRemainingTime(std::chrono::duration<Rep, Period> remaining, Qt::TimerType type)
|
||||||
|
|
||||||
|
Sets the remaining time for this QDeadlineTimer object to \a remaining. If
|
||||||
|
\a remaining is zero or negative, this QDeadlineTimer object will be mark
|
||||||
|
as expired, whereas if \a remaining is equal to \c{duration::max()}, the
|
||||||
|
object will be set to never expire.
|
||||||
|
|
||||||
|
The timer type for this QDeadlineTimer object will be set to \a timerType type.
|
||||||
|
|
||||||
|
This function can be used with C++14's user-defined literals for time, such as in:
|
||||||
|
|
||||||
|
\code
|
||||||
|
using namespace std::chrono;
|
||||||
|
deadline.setRemainingTime(250ms);
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\sa setDeadline(), remainingTime<Duration>(), hasExpired(), isForever()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, unsigned nsecs, Qt::TimerType type)
|
||||||
|
|
||||||
|
Sets the remaining time for this QDeadlineTimer object to \a secs seconds
|
||||||
|
and \a nsecs nanoseconds from now, if \a secs is a positive value. If both
|
||||||
|
values are zero, this QDeadlineTimer object will be marked as expired,
|
||||||
|
whereas if \a secs is -1, it will set it to never expire.
|
||||||
|
|
||||||
|
If value of \a nsecs is more than 1 billion nanoseconds (1 second), this
|
||||||
|
function will adjust \a secs accordingly.
|
||||||
|
|
||||||
|
The timer type for this QDeadlineTimer object will be set to \a timerType type.
|
||||||
|
|
||||||
|
\sa setRemainingTime(), hasExpired(), isForever(), remainingTime()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\overload
|
||||||
|
\fn Duration QDeadlineTimer::remainingTime() const
|
||||||
|
|
||||||
|
Returns a \c{std::chrono::duration} object of type \c{Duration} containing
|
||||||
|
the remaining time in this QDeadlineTimer, if it still has time left. If
|
||||||
|
the deadline has passed, this returns \c{Duration::zero()}, whereas if the
|
||||||
|
object is set to never expire, it returns \c{Duration::max()} (instead of
|
||||||
|
-1).
|
||||||
|
|
||||||
|
It is not possible to obtain the overdue time for expired timers with this
|
||||||
|
function. To do that, see deadline().
|
||||||
|
|
||||||
|
\note The overload of this function without template parameter always
|
||||||
|
returns milliseconds.
|
||||||
|
|
||||||
|
\sa setRemainingTime(), deadline<Clock, Duration>()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\overload
|
||||||
|
\fn std::chrono::time_point<Clock, Duration> QDeadlineTimer::deadline() const
|
||||||
|
|
||||||
|
Returns the absolute time point for the deadline stored in QDeadlineTimer
|
||||||
|
object as a \c{std::chrono::time_point} object. The template parameter
|
||||||
|
\c{Clock} is mandatory and indicates which of the C++ timekeeping clocks to
|
||||||
|
use as a reference. The value will be in the past if this QDeadlineTimer
|
||||||
|
has expired.
|
||||||
|
|
||||||
|
If this QDeadlineTimer never expires, this function returns
|
||||||
|
\c{std::chrono::time_point<Clock, Duration>::max()}.
|
||||||
|
|
||||||
|
This function can be used to calculate the amount of time a timer is
|
||||||
|
overdue, by subtracting the current time point of the reference clock, as
|
||||||
|
in the following example:
|
||||||
|
|
||||||
|
\code
|
||||||
|
auto realTimeLeft = std::chrono::nanoseconds::max();
|
||||||
|
auto tp = deadline.deadline<std::chrono::steady_clock>();
|
||||||
|
if (tp != std::chrono::steady_clock::max())
|
||||||
|
realTimeLeft = tp - std::chrono::steady_clock::now();
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\note Timers that were created as expired have an indetermine time point in
|
||||||
|
the past as their deadline, so the above calculation may not work.
|
||||||
|
|
||||||
|
\sa remainingTime(), deadlineNSecs(), setDeadline()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns true if this QDeadlineTimer object never expires, false otherwise.
|
||||||
|
For timers that never expire, remainingTime() always returns -1 and
|
||||||
|
deadline() returns the maximum value.
|
||||||
|
|
||||||
|
\sa ForeverConstant, hasExpired(), remainingTime()
|
||||||
|
*/
|
||||||
|
bool QDeadlineTimer::isForever() const Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
return t1 == (std::numeric_limits<qint64>::max)();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns true if this QDeadlineTimer object has expired, false if there
|
||||||
|
remains time left. For objects that have expired, remainingTime() will
|
||||||
|
return zero and deadline() will return a time point in the past.
|
||||||
|
|
||||||
|
QDeadlineTimer objects created with the \ref{ForeverConstant} never expire
|
||||||
|
and this function always returns false for them.
|
||||||
|
|
||||||
|
\sa isForever(), remainingTime()
|
||||||
|
*/
|
||||||
|
bool QDeadlineTimer::hasExpired() const Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
if (isForever())
|
||||||
|
return false;
|
||||||
|
return *this <= current(timerType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn Qt::TimerType QDeadlineTimer::timerType() const Q_DECL_NOTHROW
|
||||||
|
|
||||||
|
Returns the timer type is active for this object.
|
||||||
|
|
||||||
|
\sa setTimerType()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Changes the timer type for this object to \a timerType.
|
||||||
|
|
||||||
|
The behavior for each possible value of \a timerType is operating-system
|
||||||
|
dependent. Qt::PreciseTimer will use the most precise timer that Qt can
|
||||||
|
find, with resolution of 1 millisecond or better, whereas QDeadlineTimer
|
||||||
|
will try to use a more coarse timer for Qt::CoarseTimer and
|
||||||
|
Qt::VeryCoarseTimer.
|
||||||
|
|
||||||
|
\sa timerType()
|
||||||
|
*/
|
||||||
|
void QDeadlineTimer::setTimerType(Qt::TimerType timerType)
|
||||||
|
{
|
||||||
|
type = timerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the remaining time in this QDeadlineTimer object in milliseconds.
|
||||||
|
If the timer has already expired, this function will return zero and it is
|
||||||
|
not possible to obtain the amount of time overdue with this function (to do
|
||||||
|
that, see deadline()). If the timer was set to never expire, this function
|
||||||
|
returns -1.
|
||||||
|
|
||||||
|
This function is suitable for use in Qt APIs that take a millisecond
|
||||||
|
timeout, such as the many \ref QIODevice \c waitFor functions or the timed
|
||||||
|
lock functions in \ref QMutex, \ref QWaitCondition, \ref QSemaphore, or
|
||||||
|
\ref QReadWriteLock. For example:
|
||||||
|
|
||||||
|
\code
|
||||||
|
mutex.tryLock(deadline.remainingTime());
|
||||||
|
\code
|
||||||
|
|
||||||
|
\sa remainingTimeNSecs(), isForever(), hasExpired()
|
||||||
|
*/
|
||||||
|
qint64 QDeadlineTimer::remainingTime() const Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
qint64 ns = remainingTimeNSecs();
|
||||||
|
return ns <= 0 ? ns : ns / (1000 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the remaining time in this QDeadlineTimer object in nanoseconds. If
|
||||||
|
the timer has already expired, this function will return zero and it is not
|
||||||
|
possible to obtain the amount of time overdue with this function. If the
|
||||||
|
timer was set to never expire, this function returns -1.
|
||||||
|
|
||||||
|
\sa remainingTime(), isForever(), hasExpired()
|
||||||
|
*/
|
||||||
|
qint64 QDeadlineTimer::remainingTimeNSecs() const Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
if (isForever())
|
||||||
|
return -1;
|
||||||
|
qint64 raw = rawRemainingTimeNSecs();
|
||||||
|
return raw < 0 ? 0 : raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
Same as remainingTimeNSecs, but may return negative remaining times. Does
|
||||||
|
not deal with Forever.
|
||||||
|
*/
|
||||||
|
qint64 QDeadlineTimer::rawRemainingTimeNSecs() const Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
QDeadlineTimer now = current(timerType());
|
||||||
|
if (QDeadlineTimerNanosecondsInT2)
|
||||||
|
return (t1 - now.t1) * (1000*1000*1000) + t2 - now.t2;
|
||||||
|
return t1 - now.t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the absolute time point for the deadline stored in QDeadlineTimer
|
||||||
|
object, calculated in milliseconds relative to the reference clock, the
|
||||||
|
same as QElapsedTimer::msecsSinceReference(). The value will be in the past
|
||||||
|
if this QDeadlineTimer has expired.
|
||||||
|
|
||||||
|
If this QDeadlineTimer never expires, this function returns
|
||||||
|
\c{std::numeric_limits<qint64>::max()}.
|
||||||
|
|
||||||
|
This function can be used to calculate the amount of time a timer is
|
||||||
|
overdue, by subtracting QDeadlineTimer::current() or
|
||||||
|
QElapsedTimer::msecsSinceReference(), as in the following example:
|
||||||
|
|
||||||
|
\code
|
||||||
|
qint64 realTimeLeft = deadline.deadline();
|
||||||
|
if (realTimeLeft != (std::numeric_limits<qint64>::max)()) {
|
||||||
|
realTimeLeft -= QDeadlineTimer::current().deadline();
|
||||||
|
// or:
|
||||||
|
//QElapsedTimer timer;
|
||||||
|
//timer.start();
|
||||||
|
//realTimeLeft -= timer.msecsSinceReference();
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\note Timers that were created as expired have an indetermine time point in
|
||||||
|
the past as their deadline, so the above calculation may not work.
|
||||||
|
|
||||||
|
\sa remainingTime(), deadlineNSecs(), setDeadline()
|
||||||
|
*/
|
||||||
|
qint64 QDeadlineTimer::deadline() const Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
if (isForever())
|
||||||
|
return t1;
|
||||||
|
return deadlineNSecs() / (1000 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the absolute time point for the deadline stored in QDeadlineTimer
|
||||||
|
object, calculated in nanoseconds relative to the reference clock, the
|
||||||
|
same as QElapsedTimer::msecsSinceReference(). The value will be in the past
|
||||||
|
if this QDeadlineTimer has expired.
|
||||||
|
|
||||||
|
If this QDeadlineTimer never expires, this function returns
|
||||||
|
\c{std::numeric_limits<qint64>::max()}.
|
||||||
|
|
||||||
|
This function can be used to calculate the amount of time a timer is
|
||||||
|
overdue, by subtracting QDeadlineTimer::current(), as in the following
|
||||||
|
example:
|
||||||
|
|
||||||
|
\code
|
||||||
|
qint64 realTimeLeft = deadline.deadlineNSecs();
|
||||||
|
if (realTimeLeft != std::numeric_limits<qint64>::max())
|
||||||
|
realTimeLeft -= QDeadlineTimer::current().deadlineNSecs();
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\note Timers that were created as expired have an indetermine time point in
|
||||||
|
the past as their deadline, so the above calculation may not work.
|
||||||
|
|
||||||
|
\sa remainingTime(), deadlineNSecs()
|
||||||
|
*/
|
||||||
|
qint64 QDeadlineTimer::deadlineNSecs() const Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
if (isForever())
|
||||||
|
return t1;
|
||||||
|
if (QDeadlineTimerNanosecondsInT2)
|
||||||
|
return t1 * 1000 * 1000 * 1000 + t2;
|
||||||
|
return t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the deadline for this QDeadlineTimer object to be the \a msecs
|
||||||
|
absolute time point, counted in milliseconds since the reference clock (the
|
||||||
|
same as QElapsedTimer::msecsSinceReference()), and the timer type to \a
|
||||||
|
timerType. If the value is in the past, this QDeadlineTimer will be marked
|
||||||
|
as expired.
|
||||||
|
|
||||||
|
If \a msecs is \c{std::numeric_limits<qint64>::max()}, this QDeadlineTimer
|
||||||
|
will be set to never expire.
|
||||||
|
|
||||||
|
\sa setPreciseDeadline(), deadline(), deadlineNSecs(), setRemainingTime()
|
||||||
|
*/
|
||||||
|
void QDeadlineTimer::setDeadline(qint64 msecs, Qt::TimerType timerType) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
if (msecs == (std::numeric_limits<qint64>::max)()) {
|
||||||
|
setPreciseDeadline(msecs, 0, timerType); // msecs == MAX implies Forever
|
||||||
|
} else {
|
||||||
|
setPreciseDeadline(msecs / 1000, msecs % 1000 * 1000 * 1000, timerType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the deadline for this QDeadlineTimer object to be \a secs seconds and
|
||||||
|
\a nsecs nanoseconds since the reference clock epoch (the same as
|
||||||
|
QElapsedTimer::msecsSinceReference()), and the timer type to \a timerType.
|
||||||
|
If the value is in the past, this QDeadlineTimer will be marked as expired.
|
||||||
|
|
||||||
|
If \a secs or \a nsecs is \c{std::numeric_limits<qint64>::max()}, this
|
||||||
|
QDeadlineTimer will be set to never expire. If \a nsecs is more than 1
|
||||||
|
billion nanoseconds (1 second), then \a secs will be adjusted accordingly.
|
||||||
|
|
||||||
|
\sa setDeadline(), deadline(), deadlineNSecs(), setRemainingTime()
|
||||||
|
*/
|
||||||
|
void QDeadlineTimer::setPreciseDeadline(qint64 secs, qint64 nsecs, Qt::TimerType timerType) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
type = timerType;
|
||||||
|
if (secs == (std::numeric_limits<qint64>::max)() || nsecs == (std::numeric_limits<qint64>::max)()) {
|
||||||
|
*this = QDeadlineTimer(Forever, timerType);
|
||||||
|
} else if (QDeadlineTimerNanosecondsInT2) {
|
||||||
|
t1 = secs + toSecsAndNSecs(nsecs).first;
|
||||||
|
t2 = toSecsAndNSecs(nsecs).second;
|
||||||
|
} else {
|
||||||
|
t1 = secs * (1000*1000*1000) + nsecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns a QDeadlineTimer object whose deadline is extended from \a dt's
|
||||||
|
deadline by \a nsecs nanoseconds. If \a dt was set to never expire, this
|
||||||
|
function returns a QDeadlineTimer that will not expire either.
|
||||||
|
|
||||||
|
\note if \a dt was created as expired, its deadline is indeterminate and
|
||||||
|
adding an amount of time may or may not cause it to become unexpired.
|
||||||
|
*/
|
||||||
|
QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
if (dt.isForever() || nsecs == (std::numeric_limits<qint64>::max)()) {
|
||||||
|
dt = QDeadlineTimer(Forever, dt.timerType());
|
||||||
|
} else if (QDeadlineTimerNanosecondsInT2) {
|
||||||
|
dt.t1 += toSecsAndNSecs(nsecs).first;
|
||||||
|
dt.t2 += toSecsAndNSecs(nsecs).second;
|
||||||
|
if (dt.t2 > 1000*1000*1000) {
|
||||||
|
dt.t2 -= 1000*1000*1000;
|
||||||
|
++dt.t1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dt.t1 += nsecs;
|
||||||
|
}
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType)
|
||||||
|
|
||||||
|
Returns a QDeadlineTimer that is expired but is guaranteed to contain the
|
||||||
|
current time. Objects created by this function can participate in the
|
||||||
|
calculation of how long a timer is overdue, using the deadline() function.
|
||||||
|
|
||||||
|
The QDeadlineTimer object will be constructed with a timer type of \a
|
||||||
|
timerType.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn qint64 QDeadlineTimer::resolution(Qt::TimerType timerType)
|
||||||
|
|
||||||
|
Returns the resolution in nanoseconds of the system clock that backs timers
|
||||||
|
of type \a timerType, or 0 if the resolution could not be determined.
|
||||||
|
|
||||||
|
The resolution is not a guarantee that applications will get time values
|
||||||
|
with an accuracy down to that level. It is only the minimum change value
|
||||||
|
that can be expected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool operator==(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
\related QDeadlineTimer
|
||||||
|
|
||||||
|
Returns true if the deadline on \a d1 and the deadline in \a d2 are the
|
||||||
|
same, false otherwise. The timer type used to create the two deadlines is
|
||||||
|
ignored. This function is equivalent to:
|
||||||
|
|
||||||
|
\code
|
||||||
|
return d1.deadlineNSecs() == d2.deadlineNSecs();
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\note comparing QDeadlineTimer objects with different timer types is
|
||||||
|
not supported and may result in unpredictable behavior.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool operator!=(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
\related QDeadlineTimer
|
||||||
|
|
||||||
|
Returns true if the deadline on \a d1 and the deadline in \a d2 are
|
||||||
|
diferent, false otherwise. The timer type used to create the two deadlines
|
||||||
|
is ignored. This function is equivalent to:
|
||||||
|
|
||||||
|
\code
|
||||||
|
return d1.deadlineNSecs() != d2.deadlineNSecs();
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\note comparing QDeadlineTimer objects with different timer types is
|
||||||
|
not supported and may result in unpredictable behavior.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool operator<(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
\related QDeadlineTimer
|
||||||
|
|
||||||
|
Returns true if the deadline on \a d1 is earlier than the deadline in \a
|
||||||
|
d2, false otherwise. The timer type used to create the two deadlines is
|
||||||
|
ignored. This function is equivalent to:
|
||||||
|
|
||||||
|
\code
|
||||||
|
return d1.deadlineNSecs() < d2.deadlineNSecs();
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\note comparing QDeadlineTimer objects with different timer types is
|
||||||
|
not supported and may result in unpredictable behavior.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool operator<=(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
\related QDeadlineTimer
|
||||||
|
|
||||||
|
Returns true if the deadline on \a d1 is earlier than or the same as the
|
||||||
|
deadline in \a d2, false otherwise. The timer type used to create the two
|
||||||
|
deadlines is ignored. This function is equivalent to:
|
||||||
|
|
||||||
|
\code
|
||||||
|
return d1.deadlineNSecs() <= d2.deadlineNSecs();
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\note comparing QDeadlineTimer objects with different timer types is
|
||||||
|
not supported and may result in unpredictable behavior.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool operator>(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
\related QDeadlineTimer
|
||||||
|
|
||||||
|
Returns true if the deadline on \a d1 is later than the deadline in \a
|
||||||
|
d2, false otherwise. The timer type used to create the two deadlines is
|
||||||
|
ignored. This function is equivalent to:
|
||||||
|
|
||||||
|
\code
|
||||||
|
return d1.deadlineNSecs() > d2.deadlineNSecs();
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\note comparing QDeadlineTimer objects with different timer types is
|
||||||
|
not supported and may result in unpredictable behavior.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool operator>=(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
\related QDeadlineTimer
|
||||||
|
|
||||||
|
Returns true if the deadline on \a d1 is later than or the same as the
|
||||||
|
deadline in \a d2, false otherwise. The timer type used to create the two
|
||||||
|
deadlines is ignored. This function is equivalent to:
|
||||||
|
|
||||||
|
\code
|
||||||
|
return d1.deadlineNSecs() >= d2.deadlineNSecs();
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\note comparing QDeadlineTimer objects with different timer types is
|
||||||
|
not supported and may result in unpredictable behavior.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs)
|
||||||
|
\related QDeadlineTimer
|
||||||
|
|
||||||
|
Returns a QDeadlineTimer object whose deadline is \a msecs later than the
|
||||||
|
deadline stored in \a dt. If \a dt is set to never expire, this function
|
||||||
|
returns a QDeadlineTimer that does not expire either.
|
||||||
|
|
||||||
|
To add times of precision greater than 1 millisecond, use addNSecs().
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QDeadlineTimer operator+(qint64 msecs, QDeadlineTimer dt)
|
||||||
|
\related QDeadlineTimer
|
||||||
|
|
||||||
|
Returns a QDeadlineTimer object whose deadline is \a msecs later than the
|
||||||
|
deadline stored in \a dt. If \a dt is set to never expire, this function
|
||||||
|
returns a QDeadlineTimer that does not expire either.
|
||||||
|
|
||||||
|
To add times of precision greater than 1 millisecond, use addNSecs().
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QDeadlineTimer operator-(QDeadlineTimer dt, qint64 msecs)
|
||||||
|
\related QDeadlineTimer
|
||||||
|
|
||||||
|
Returns a QDeadlineTimer object whose deadline is \a msecs before the
|
||||||
|
deadline stored in \a dt. If \a dt is set to never expire, this function
|
||||||
|
returns a QDeadlineTimer that does not expire either.
|
||||||
|
|
||||||
|
To subtract times of precision greater than 1 millisecond, use addNSecs().
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QDeadlineTimer &QDeadlineTimer::operator+=(qint64 msecs)
|
||||||
|
|
||||||
|
Extends this QDeadlineTimer object by \a msecs milliseconds and returns
|
||||||
|
itself. If this object is set to never expire, this function does nothing.
|
||||||
|
|
||||||
|
To add times of precision greater than 1 millisecond, use addNSecs().
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn QDeadlineTimer &QDeadlineTimer::operator-=(qint64 msecs)
|
||||||
|
|
||||||
|
Shortens this QDeadlineTimer object by \a msecs milliseconds and returns
|
||||||
|
itself. If this object is set to never expire, this function does nothing.
|
||||||
|
|
||||||
|
To subtract times of precision greater than 1 millisecond, use addNSecs().
|
||||||
|
*/
|
||||||
|
|
||||||
|
// the rest of the functions are in qelapsedtimer_xxx.cpp
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
190
src/corelib/kernel/qdeadlinetimer.h
Normal file
190
src/corelib/kernel/qdeadlinetimer.h
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 Intel Corporation.
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the QtCore module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL21$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** As a special exception, The Qt Company gives you certain additional
|
||||||
|
** rights. These rights are described in The Qt Company LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QDEADLINETIMER_H
|
||||||
|
#define QDEADLINETIMER_H
|
||||||
|
|
||||||
|
#include <QtCore/qelapsedtimer.h>
|
||||||
|
#include <QtCore/qmetatype.h>
|
||||||
|
#include <QtCore/qnamespace.h>
|
||||||
|
|
||||||
|
#ifdef max
|
||||||
|
// un-pollute the namespace. We need std::numeric_limits::max() and std::chrono::duration::max()
|
||||||
|
# undef max
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#if QT_HAS_INCLUDE(<chrono>)
|
||||||
|
# include <chrono>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class Q_CORE_EXPORT QDeadlineTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ForeverConstant { Forever };
|
||||||
|
|
||||||
|
Q_DECL_CONSTEXPR QDeadlineTimer(Qt::TimerType type_ = Qt::CoarseTimer) Q_DECL_NOTHROW
|
||||||
|
: t1(0), t2(0), type(type_) {}
|
||||||
|
Q_DECL_CONSTEXPR QDeadlineTimer(ForeverConstant, Qt::TimerType type_ = Qt::CoarseTimer) Q_DECL_NOTHROW
|
||||||
|
: t1(std::numeric_limits<qint64>::max()), t2(0), type(type_) {}
|
||||||
|
explicit QDeadlineTimer(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW;
|
||||||
|
|
||||||
|
void swap(QDeadlineTimer &other)
|
||||||
|
{ qSwap(t1, other.t1); qSwap(t2, other.t2); qSwap(type, other.type); }
|
||||||
|
|
||||||
|
bool isForever() const Q_DECL_NOTHROW;
|
||||||
|
bool hasExpired() const Q_DECL_NOTHROW;
|
||||||
|
|
||||||
|
Qt::TimerType timerType() const Q_DECL_NOTHROW
|
||||||
|
{ return Qt::TimerType(type & 0xff); }
|
||||||
|
void setTimerType(Qt::TimerType type);
|
||||||
|
|
||||||
|
qint64 remainingTime() const Q_DECL_NOTHROW;
|
||||||
|
qint64 remainingTimeNSecs() const Q_DECL_NOTHROW;
|
||||||
|
void setRemainingTime(qint64 msecs, Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW;
|
||||||
|
void setPreciseRemainingTime(qint64 secs, qint64 nsecs = 0,
|
||||||
|
Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW;
|
||||||
|
|
||||||
|
qint64 deadline() const Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION;
|
||||||
|
qint64 deadlineNSecs() const Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION;
|
||||||
|
void setDeadline(qint64 msecs, Qt::TimerType timerType = Qt::CoarseTimer) Q_DECL_NOTHROW;
|
||||||
|
void setPreciseDeadline(qint64 secs, qint64 nsecs = 0,
|
||||||
|
Qt::TimerType type = Qt::CoarseTimer) Q_DECL_NOTHROW;
|
||||||
|
|
||||||
|
static QDeadlineTimer addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_NOTHROW Q_DECL_PURE_FUNCTION;
|
||||||
|
static QDeadlineTimer current(Qt::TimerType timerType = Qt::CoarseTimer) Q_DECL_NOTHROW;
|
||||||
|
|
||||||
|
friend bool operator==(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
{ return d1.t1 == d2.t1 && d1.t2 == d2.t2; }
|
||||||
|
friend bool operator!=(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
{ return !(d1 == d2); }
|
||||||
|
friend bool operator<(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
{ return d1.t1 < d2.t1 || (d1.t1 == d2.t1 && d1.t2 < d2.t2); }
|
||||||
|
friend bool operator<=(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
{ return d1 == d2 || d1 < d2; }
|
||||||
|
friend bool operator>(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
{ return d2 < d1; }
|
||||||
|
friend bool operator>=(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
{ return !(d1 < d2); }
|
||||||
|
|
||||||
|
friend QDeadlineTimer operator+(QDeadlineTimer dt, qint64 msecs)
|
||||||
|
{ return QDeadlineTimer::addNSecs(dt, msecs * 1000 * 1000); }
|
||||||
|
friend QDeadlineTimer operator+(qint64 msecs, QDeadlineTimer dt)
|
||||||
|
{ return dt + msecs; }
|
||||||
|
friend QDeadlineTimer operator-(QDeadlineTimer dt, qint64 msecs)
|
||||||
|
{ return dt + (-msecs); }
|
||||||
|
friend qint64 operator-(QDeadlineTimer dt1, QDeadlineTimer dt2)
|
||||||
|
{ return (dt1.deadlineNSecs() - dt2.deadlineNSecs()) / (1000 * 1000); }
|
||||||
|
QDeadlineTimer &operator+=(qint64 msecs)
|
||||||
|
{ *this = *this + msecs; return *this; }
|
||||||
|
QDeadlineTimer &operator-=(qint64 msecs)
|
||||||
|
{ *this = *this + (-msecs); return *this; }
|
||||||
|
|
||||||
|
#if QT_HAS_INCLUDE(<chrono>) || defined(Q_QDOC)
|
||||||
|
template <class Clock, class Duration>
|
||||||
|
QDeadlineTimer(std::chrono::time_point<Clock, Duration> deadline_,
|
||||||
|
Qt::TimerType type_ = Qt::CoarseTimer) : t2(0)
|
||||||
|
{ setDeadline(deadline_, type_); }
|
||||||
|
template <class Clock, class Duration>
|
||||||
|
QDeadlineTimer &operator=(std::chrono::time_point<Clock, Duration> deadline_)
|
||||||
|
{ setDeadline(deadline_); return *this; }
|
||||||
|
|
||||||
|
template <class Clock, class Duration>
|
||||||
|
void setDeadline(std::chrono::time_point<Clock, Duration> deadline_,
|
||||||
|
Qt::TimerType type_ = Qt::CoarseTimer)
|
||||||
|
{ setRemainingTime(deadline_ == deadline_.max() ? Duration::max() : deadline_ - Clock::now(), type_); }
|
||||||
|
|
||||||
|
template <class Clock, class Duration = typename Clock::duration>
|
||||||
|
std::chrono::time_point<Clock, Duration> deadline() const
|
||||||
|
{
|
||||||
|
auto val = std::chrono::nanoseconds(rawRemainingTimeNSecs()) + Clock::now();
|
||||||
|
return std::chrono::time_point_cast<Duration>(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
QDeadlineTimer(std::chrono::duration<Rep, Period> remaining, Qt::TimerType type_ = Qt::CoarseTimer)
|
||||||
|
: t2(0)
|
||||||
|
{ setRemainingTime(remaining, type_); }
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
QDeadlineTimer &operator=(std::chrono::duration<Rep, Period> remaining)
|
||||||
|
{ setRemainingTime(remaining); return *this; }
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
void setRemainingTime(std::chrono::duration<Rep, Period> remaining, Qt::TimerType type_ = Qt::CoarseTimer)
|
||||||
|
{
|
||||||
|
if (remaining == remaining.max())
|
||||||
|
*this = QDeadlineTimer(Forever, type_);
|
||||||
|
else
|
||||||
|
setPreciseRemainingTime(0, std::chrono::nanoseconds(remaining).count(), type_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::nanoseconds remainingTimeAsDuration() const Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
if (isForever())
|
||||||
|
return std::chrono::nanoseconds::max();
|
||||||
|
qint64 nsecs = rawRemainingTimeNSecs();
|
||||||
|
if (nsecs <= 0)
|
||||||
|
return std::chrono::nanoseconds::zero();
|
||||||
|
return std::chrono::nanoseconds(nsecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Rep, class Period>
|
||||||
|
friend QDeadlineTimer operator+(QDeadlineTimer dt, std::chrono::duration<Rep, Period> value)
|
||||||
|
{ return QDeadlineTimer::addNSecs(dt, std::chrono::duration_cast<std::chrono::nanoseconds>(value).count()); }
|
||||||
|
template <class Rep, class Period>
|
||||||
|
friend QDeadlineTimer operator+(std::chrono::duration<Rep, Period> value, QDeadlineTimer dt)
|
||||||
|
{ return dt + value; }
|
||||||
|
template <class Rep, class Period>
|
||||||
|
friend QDeadlineTimer operator+=(QDeadlineTimer &dt, std::chrono::duration<Rep, Period> value)
|
||||||
|
{ return dt = dt + value; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
qint64 t1;
|
||||||
|
unsigned t2;
|
||||||
|
unsigned type;
|
||||||
|
|
||||||
|
qint64 rawRemainingTimeNSecs() const Q_DECL_NOTHROW;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_SHARED(QDeadlineTimer)
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(QDeadlineTimer)
|
||||||
|
|
||||||
|
#endif // QDEADLINETIMER_H
|
59
src/corelib/kernel/qdeadlinetimer_p.h
Normal file
59
src/corelib/kernel/qdeadlinetimer_p.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the QtCore module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 2.0 or (at your option) the GNU General
|
||||||
|
** Public license version 3 or any later version approved by the KDE Free
|
||||||
|
** Qt Foundation. The licenses are as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||||
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QDEADLINETIMER_P_H
|
||||||
|
#define QDEADLINETIMER_P_H
|
||||||
|
|
||||||
|
#include <QtCore/qglobal.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
enum {
|
||||||
|
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||||||
|
// t1 contains seconds and t2 contains nanoseconds
|
||||||
|
QDeadlineTimerNanosecondsInT2 = 1
|
||||||
|
#else
|
||||||
|
// t1 contains nanoseconds, t2 is always zero
|
||||||
|
QDeadlineTimerNanosecondsInT2 = 0
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif
|
@ -83,6 +83,9 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
\snippet qelapsedtimer/main.cpp 2
|
\snippet qelapsedtimer/main.cpp 2
|
||||||
|
|
||||||
|
It is often more convenient to use \ref{QDeadlineTimer} in this case, which
|
||||||
|
counts towards a timeout in the future instead of tracking elapsed time.
|
||||||
|
|
||||||
\section1 Reference Clocks
|
\section1 Reference Clocks
|
||||||
|
|
||||||
QElapsedTimer will use the platform's monotonic reference clock in all
|
QElapsedTimer will use the platform's monotonic reference clock in all
|
||||||
@ -120,7 +123,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
The information on which clocks types may overflow and how to remedy that
|
The information on which clocks types may overflow and how to remedy that
|
||||||
issue is documented along with the clock types.
|
issue is documented along with the clock types.
|
||||||
|
|
||||||
\sa QTime, QTimer
|
\sa QTime, QTimer, QDeadlineTimer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -255,7 +258,7 @@ bool QElapsedTimer::isValid() const Q_DECL_NOTHROW
|
|||||||
The value of \a timeout can be -1 to indicate that this timer does not
|
The value of \a timeout can be -1 to indicate that this timer does not
|
||||||
expire, in which case this function will always return false.
|
expire, in which case this function will always return false.
|
||||||
|
|
||||||
\sa elapsed()
|
\sa elapsed(), QDeadlineTimer
|
||||||
*/
|
*/
|
||||||
bool QElapsedTimer::hasExpired(qint64 timeout) const Q_DECL_NOTHROW
|
bool QElapsedTimer::hasExpired(qint64 timeout) const Q_DECL_NOTHROW
|
||||||
{
|
{
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qelapsedtimer.h"
|
#include "qelapsedtimer.h"
|
||||||
|
#include "qdeadlinetimer.h"
|
||||||
#include "qdatetime.h"
|
#include "qdatetime.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -201,4 +202,12 @@ bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
|
|||||||
return v1.t1 < v2.t1;
|
return v1.t1 < v2.t1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
QDeadlineTimer result;
|
||||||
|
result.t1 = QDateTime::currentMSecsSinceEpoch() * 1000 * 1000;
|
||||||
|
result.type = timerType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
#include "qelapsedtimer.h"
|
#include "qelapsedtimer.h"
|
||||||
|
#include "qdeadlinetimer.h"
|
||||||
|
#include "qdeadlinetimer_p.h"
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -50,6 +52,12 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
#ifdef __LP64__
|
||||||
|
typedef __int128_t LargeInt;
|
||||||
|
#else
|
||||||
|
typedef qint64 LargeInt;
|
||||||
|
#endif
|
||||||
|
|
||||||
QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
|
QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
|
||||||
{
|
{
|
||||||
return MachAbsoluteTime;
|
return MachAbsoluteTime;
|
||||||
@ -65,13 +73,13 @@ static qint64 absoluteToNSecs(qint64 cpuTime)
|
|||||||
{
|
{
|
||||||
if (info.denom == 0)
|
if (info.denom == 0)
|
||||||
mach_timebase_info(&info);
|
mach_timebase_info(&info);
|
||||||
#ifdef __LP64__
|
|
||||||
__uint128_t nsecs = static_cast<__uint128_t>(cpuTime) * info.numer / info.denom;
|
// don't do multiplication & division if those are equal
|
||||||
return static_cast<qint64>(nsecs);
|
// (mathematically it would be the same, but it's computationally expensive)
|
||||||
#else
|
if (info.numer == info.denom)
|
||||||
qint64 nsecs = cpuTime * info.numer / info.denom;
|
return cpuTime;
|
||||||
|
qint64 nsecs = LargeInt(cpuTime) * info.numer / info.denom;
|
||||||
return nsecs;
|
return nsecs;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static qint64 absoluteToMSecs(qint64 cpuTime)
|
static qint64 absoluteToMSecs(qint64 cpuTime)
|
||||||
@ -146,4 +154,13 @@ bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
|
|||||||
return v1.t1 < v2.t1;
|
return v1.t1 < v2.t1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
Q_STATIC_ASSERT(!QDeadlineTimerNanosecondsInT2);
|
||||||
|
QDeadlineTimer result;
|
||||||
|
result.type = timerType;
|
||||||
|
result.t1 = absoluteToNSecs(mach_absolute_time());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qelapsedtimer.h"
|
#include "qelapsedtimer.h"
|
||||||
|
#include "qdeadlinetimer.h"
|
||||||
|
#include "qdeadlinetimer_p.h"
|
||||||
#if defined(Q_OS_VXWORKS)
|
#if defined(Q_OS_VXWORKS)
|
||||||
#include "qfunctions_vxworks.h"
|
#include "qfunctions_vxworks.h"
|
||||||
#else
|
#else
|
||||||
@ -248,4 +250,16 @@ bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
|
|||||||
return v1.t1 < v2.t1 || (v1.t1 == v2.t1 && v1.t2 < v2.t2);
|
return v1.t1 < v2.t1 || (v1.t1 == v2.t1 && v1.t2 < v2.t2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
Q_STATIC_ASSERT(QDeadlineTimerNanosecondsInT2);
|
||||||
|
QDeadlineTimer result;
|
||||||
|
qint64 cursec, curnsec;
|
||||||
|
do_gettime(&cursec, &curnsec);
|
||||||
|
result.t1 = cursec;
|
||||||
|
result.t2 = curnsec;
|
||||||
|
result.type = timerType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qelapsedtimer.h"
|
#include "qelapsedtimer.h"
|
||||||
|
#include "qdeadlinetimer.h"
|
||||||
|
#include "qdeadlinetimer_p.h"
|
||||||
#include <qt_windows.h>
|
#include <qt_windows.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -76,6 +78,17 @@ static inline qint64 ticksToNanoseconds(qint64 ticks)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline qint64 nanosecondsToTicks(qint64 nsec)
|
||||||
|
{
|
||||||
|
if (counterFrequency > 0) {
|
||||||
|
// QueryPerformanceCounter uses an arbitrary frequency
|
||||||
|
return double(nsec) * counterFrequency / 1000000000.;
|
||||||
|
} else {
|
||||||
|
// GetTickCount(64) uses milliseconds
|
||||||
|
return nsec / 1000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static quint64 getTickCount()
|
static quint64 getTickCount()
|
||||||
{
|
{
|
||||||
resolveCounterFrequency();
|
resolveCounterFrequency();
|
||||||
@ -161,4 +174,13 @@ bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
|
|||||||
return (v1.t1 - v2.t1) < 0;
|
return (v1.t1 - v2.t1) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
Q_STATIC_ASSERT(!QDeadlineTimerNanosecondsInT2);
|
||||||
|
QDeadlineTimer result;
|
||||||
|
result.t1 = ticksToNanoseconds(getTickCount());
|
||||||
|
result.type = timerType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
TEMPLATE=subdirs
|
TEMPLATE=subdirs
|
||||||
SUBDIRS=\
|
SUBDIRS=\
|
||||||
qcoreapplication \
|
qcoreapplication \
|
||||||
|
qdeadlinetimer \
|
||||||
qelapsedtimer \
|
qelapsedtimer \
|
||||||
qeventdispatcher \
|
qeventdispatcher \
|
||||||
qeventloop \
|
qeventloop \
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
CONFIG += testcase
|
||||||
|
TARGET = tst_qdeadlinetimer
|
||||||
|
QT = core testlib
|
||||||
|
SOURCES = tst_qdeadlinetimer.cpp
|
||||||
|
|
625
tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp
Normal file
625
tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp
Normal file
@ -0,0 +1,625 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 Intel Corporation.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the test suite of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <QtCore/QString>
|
||||||
|
#include <QtCore/QTime>
|
||||||
|
#include <QtCore/QDeadlineTimer>
|
||||||
|
#include <QtTest/QtTest>
|
||||||
|
|
||||||
|
#if QT_HAS_INCLUDE(<chrono>)
|
||||||
|
# include <chrono>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const int minResolution = 100; // the minimum resolution for the tests
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Qt::TimerType)
|
||||||
|
|
||||||
|
class tst_QDeadlineTimer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void initTestCase_data();
|
||||||
|
void basics();
|
||||||
|
void foreverness();
|
||||||
|
void current();
|
||||||
|
void deadlines();
|
||||||
|
void setDeadline();
|
||||||
|
void expire();
|
||||||
|
void stdchrono();
|
||||||
|
};
|
||||||
|
|
||||||
|
void tst_QDeadlineTimer::initTestCase_data()
|
||||||
|
{
|
||||||
|
qRegisterMetaType<Qt::TimerType>();
|
||||||
|
QTest::addColumn<Qt::TimerType>("timerType");
|
||||||
|
QTest::newRow("precise") << Qt::PreciseTimer;
|
||||||
|
QTest::newRow("coarse") << Qt::CoarseTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QDeadlineTimer::basics()
|
||||||
|
{
|
||||||
|
QDeadlineTimer deadline;
|
||||||
|
QCOMPARE(deadline.timerType(), Qt::CoarseTimer);
|
||||||
|
|
||||||
|
QFETCH_GLOBAL(Qt::TimerType, timerType);
|
||||||
|
deadline = QDeadlineTimer(timerType);
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline, QDeadlineTimer(timerType));
|
||||||
|
QVERIFY(!(deadline != QDeadlineTimer(timerType)));
|
||||||
|
QVERIFY(!(deadline < QDeadlineTimer()));
|
||||||
|
QVERIFY(deadline <= QDeadlineTimer());
|
||||||
|
QVERIFY(deadline >= QDeadlineTimer());
|
||||||
|
QVERIFY(!(deadline > QDeadlineTimer()));
|
||||||
|
QVERIFY(!(deadline < deadline));
|
||||||
|
QVERIFY(deadline <= deadline);
|
||||||
|
QVERIFY(deadline >= deadline);
|
||||||
|
QVERIFY(!(deadline > deadline));
|
||||||
|
|
||||||
|
// should have expired, but we may be running too early after boot
|
||||||
|
QTRY_VERIFY_WITH_TIMEOUT(deadline.hasExpired(), 100);
|
||||||
|
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(0));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
|
||||||
|
QCOMPARE(deadline.deadline(), qint64(0));
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), qint64(0));
|
||||||
|
|
||||||
|
deadline.setRemainingTime(0, timerType);
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(0));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
|
||||||
|
QVERIFY(deadline.deadline() != 0);
|
||||||
|
QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != 0);
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
deadline.setPreciseRemainingTime(0, 0, timerType);
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(0));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
|
||||||
|
QVERIFY(deadline.deadline() != 0);
|
||||||
|
QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != 0);
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
deadline.setDeadline(0, timerType);
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(0));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
|
||||||
|
QCOMPARE(deadline.deadline(), qint64(0));
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), qint64(0));
|
||||||
|
|
||||||
|
deadline.setPreciseDeadline(0, 0, timerType);
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(0));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
|
||||||
|
QCOMPARE(deadline.deadline(), qint64(0));
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), qint64(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QDeadlineTimer::foreverness()
|
||||||
|
{
|
||||||
|
QFETCH_GLOBAL(Qt::TimerType, timerType);
|
||||||
|
// we don't check whether timerType() is our type since it's possible it detects it's forever
|
||||||
|
|
||||||
|
QDeadlineTimer deadline = QDeadlineTimer::Forever;
|
||||||
|
QCOMPARE(deadline.timerType(), Qt::CoarseTimer);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
deadline = QDeadlineTimer(-1, timerType);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
deadline.setRemainingTime(-1, timerType);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
deadline.setPreciseRemainingTime(-1, 0, timerType);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
deadline.setPreciseRemainingTime(-1, -1, timerType);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
deadline.setDeadline(std::numeric_limits<qint64>::max(), timerType);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
deadline.setPreciseDeadline(std::numeric_limits<qint64>::max(), 0, timerType);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
|
||||||
|
QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
QCOMPARE(deadline, deadline);
|
||||||
|
QVERIFY(!(deadline < deadline));
|
||||||
|
QVERIFY(deadline <= deadline);
|
||||||
|
QVERIFY(deadline >= deadline);
|
||||||
|
QVERIFY(!(deadline > deadline));
|
||||||
|
|
||||||
|
// adding to forever must still be forever
|
||||||
|
QDeadlineTimer deadline2 = deadline + 1;
|
||||||
|
QVERIFY(deadline2.isForever());
|
||||||
|
QVERIFY(!deadline2.hasExpired());
|
||||||
|
QCOMPARE(deadline2.remainingTime(), qint64(-1));
|
||||||
|
QCOMPARE(deadline2.remainingTimeNSecs(), qint64(-1));
|
||||||
|
QCOMPARE(deadline2.deadline(), std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline2.deadlineNSecs(), std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline2.timerType(), deadline.timerType());
|
||||||
|
|
||||||
|
QCOMPARE(deadline2 - deadline, qint64(0));
|
||||||
|
QCOMPARE(deadline2, deadline);
|
||||||
|
QVERIFY(!(deadline2 < deadline));
|
||||||
|
QVERIFY(deadline2 <= deadline);
|
||||||
|
QVERIFY(deadline2 >= deadline);
|
||||||
|
QVERIFY(!(deadline2 > deadline));
|
||||||
|
|
||||||
|
// subtracting from forever is *also* forever
|
||||||
|
deadline2 = deadline - 1;
|
||||||
|
QVERIFY(deadline2.isForever());
|
||||||
|
QVERIFY(!deadline2.hasExpired());
|
||||||
|
QCOMPARE(deadline2.remainingTime(), qint64(-1));
|
||||||
|
QCOMPARE(deadline2.remainingTimeNSecs(), qint64(-1));
|
||||||
|
QCOMPARE(deadline2.deadline(), std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline2.deadlineNSecs(), std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline2.timerType(), deadline.timerType());
|
||||||
|
|
||||||
|
QCOMPARE(deadline2 - deadline, qint64(0));
|
||||||
|
QCOMPARE(deadline2, deadline);
|
||||||
|
QVERIFY(!(deadline2 < deadline));
|
||||||
|
QVERIFY(deadline2 <= deadline);
|
||||||
|
QVERIFY(deadline2 >= deadline);
|
||||||
|
QVERIFY(!(deadline2 > deadline));
|
||||||
|
|
||||||
|
// compare and order against a default-constructed object
|
||||||
|
QDeadlineTimer expired;
|
||||||
|
QVERIFY(!(deadline == expired));
|
||||||
|
QVERIFY(deadline != expired);
|
||||||
|
QVERIFY(!(deadline < expired));
|
||||||
|
QVERIFY(!(deadline <= expired));
|
||||||
|
QVERIFY(deadline >= expired);
|
||||||
|
QVERIFY(deadline > expired);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QDeadlineTimer::current()
|
||||||
|
{
|
||||||
|
QFETCH_GLOBAL(Qt::TimerType, timerType);
|
||||||
|
auto deadline = QDeadlineTimer::current(timerType);
|
||||||
|
QVERIFY(deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(0));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
|
||||||
|
QVERIFY(deadline.deadline() != 0);
|
||||||
|
QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != 0);
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
// subtracting from current should be "more expired"
|
||||||
|
QDeadlineTimer earlierDeadline = deadline - 1;
|
||||||
|
QVERIFY(earlierDeadline.hasExpired());
|
||||||
|
QVERIFY(!earlierDeadline.isForever());
|
||||||
|
QCOMPARE(earlierDeadline.timerType(), timerType);
|
||||||
|
QCOMPARE(earlierDeadline.remainingTime(), qint64(0));
|
||||||
|
QCOMPARE(earlierDeadline.remainingTimeNSecs(), qint64(0));
|
||||||
|
QVERIFY(earlierDeadline.deadline() != 0);
|
||||||
|
QVERIFY(earlierDeadline.deadline() != std::numeric_limits<qint64>::max());
|
||||||
|
QVERIFY(earlierDeadline.deadlineNSecs() != 0);
|
||||||
|
QVERIFY(earlierDeadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(earlierDeadline.deadline(), deadline.deadline() - 1);
|
||||||
|
QCOMPARE(earlierDeadline.deadlineNSecs(), deadline.deadlineNSecs() - 1000*1000);
|
||||||
|
|
||||||
|
QCOMPARE(earlierDeadline - deadline, qint64(-1));
|
||||||
|
QVERIFY(earlierDeadline != deadline);
|
||||||
|
QVERIFY(earlierDeadline < deadline);
|
||||||
|
QVERIFY(earlierDeadline <= deadline);
|
||||||
|
QVERIFY(!(earlierDeadline >= deadline));
|
||||||
|
QVERIFY(!(earlierDeadline > deadline));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QDeadlineTimer::deadlines()
|
||||||
|
{
|
||||||
|
QFETCH_GLOBAL(Qt::TimerType, timerType);
|
||||||
|
|
||||||
|
QDeadlineTimer deadline(4 * minResolution, timerType);
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(deadline.remainingTime() > (3 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTime() <= (4 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution));
|
||||||
|
QVERIFY(deadline.deadline() != 0);
|
||||||
|
QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != 0);
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
deadline.setRemainingTime(4 * minResolution, timerType);
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(deadline.remainingTime() > (3 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTime() <= (4 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution));
|
||||||
|
QVERIFY(deadline.deadline() != 0);
|
||||||
|
QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != 0);
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
deadline.setPreciseRemainingTime(0, 4000000 * minResolution, timerType);
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(deadline.remainingTime() > (3 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTime() <= (4 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution));
|
||||||
|
QVERIFY(deadline.deadline() != 0);
|
||||||
|
QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != 0);
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
deadline.setPreciseRemainingTime(1, 0, timerType); // 1 sec
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(deadline.remainingTime() > (1000 - minResolution));
|
||||||
|
QVERIFY(deadline.remainingTime() <= 1000);
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() > (1000 - minResolution)*1000*1000);
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() <= (1000*1000*1000));
|
||||||
|
QVERIFY(deadline.deadline() != 0);
|
||||||
|
QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != 0);
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
|
||||||
|
|
||||||
|
// adding to a future deadline must still be further in the future
|
||||||
|
QDeadlineTimer laterDeadline = deadline + 1;
|
||||||
|
QVERIFY(!laterDeadline.hasExpired());
|
||||||
|
QVERIFY(!laterDeadline.isForever());
|
||||||
|
QCOMPARE(laterDeadline.timerType(), timerType);
|
||||||
|
QVERIFY(laterDeadline.remainingTime() > (1000 - minResolution));
|
||||||
|
QVERIFY(laterDeadline.remainingTime() <= 1001);
|
||||||
|
QVERIFY(laterDeadline.remainingTimeNSecs() > (1001 - minResolution)*1000*1000);
|
||||||
|
QVERIFY(laterDeadline.remainingTimeNSecs() <= (1001*1000*1000));
|
||||||
|
QVERIFY(laterDeadline.deadline() != 0);
|
||||||
|
QVERIFY(laterDeadline.deadline() != std::numeric_limits<qint64>::max());
|
||||||
|
QVERIFY(laterDeadline.deadlineNSecs() != 0);
|
||||||
|
QVERIFY(laterDeadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(laterDeadline.deadline(), deadline.deadline() + 1);
|
||||||
|
QCOMPARE(laterDeadline.deadlineNSecs(), deadline.deadlineNSecs() + 1000*1000);
|
||||||
|
|
||||||
|
QCOMPARE(laterDeadline - deadline, qint64(1));
|
||||||
|
QVERIFY(laterDeadline != deadline);
|
||||||
|
QVERIFY(!(laterDeadline < deadline));
|
||||||
|
QVERIFY(!(laterDeadline <= deadline));
|
||||||
|
QVERIFY(laterDeadline >= deadline);
|
||||||
|
QVERIFY(laterDeadline > deadline);
|
||||||
|
|
||||||
|
// compare and order against a default-constructed object
|
||||||
|
QDeadlineTimer expired;
|
||||||
|
QVERIFY(!(deadline == expired));
|
||||||
|
QVERIFY(deadline != expired);
|
||||||
|
QVERIFY(!(deadline < expired));
|
||||||
|
QVERIFY(!(deadline <= expired));
|
||||||
|
QVERIFY(deadline >= expired);
|
||||||
|
QVERIFY(deadline > expired);
|
||||||
|
|
||||||
|
// compare and order against a forever deadline
|
||||||
|
QDeadlineTimer forever_(QDeadlineTimer::Forever);
|
||||||
|
QVERIFY(!(deadline == forever_));
|
||||||
|
QVERIFY(deadline != forever_);
|
||||||
|
QVERIFY(deadline < forever_);
|
||||||
|
QVERIFY(deadline <= forever_);
|
||||||
|
QVERIFY(!(deadline >= forever_));
|
||||||
|
QVERIFY(!(deadline > forever_));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QDeadlineTimer::setDeadline()
|
||||||
|
{
|
||||||
|
QFETCH_GLOBAL(Qt::TimerType, timerType);
|
||||||
|
auto now = QDeadlineTimer::current(timerType);
|
||||||
|
QDeadlineTimer deadline;
|
||||||
|
|
||||||
|
deadline.setDeadline(now.deadline(), timerType);
|
||||||
|
QVERIFY(deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(0));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
|
||||||
|
QCOMPARE(deadline.deadline(), now.deadline());
|
||||||
|
// don't check deadlineNSecs!
|
||||||
|
|
||||||
|
deadline.setPreciseDeadline(now.deadlineNSecs() / (1000 * 1000 * 1000),
|
||||||
|
now.deadlineNSecs() % (1000 * 1000 * 1000), timerType);
|
||||||
|
QVERIFY(deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(0));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
|
||||||
|
QCOMPARE(deadline.deadline(), now.deadline());
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), now.deadlineNSecs());
|
||||||
|
|
||||||
|
now = QDeadlineTimer::current(timerType);
|
||||||
|
deadline.setDeadline(now.deadline() + 4 * minResolution, timerType);
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(deadline.remainingTime() > (3 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTime() <= (4 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution));
|
||||||
|
QCOMPARE(deadline.deadline(), now.deadline() + 4 * minResolution); // yes, it's exact
|
||||||
|
// don't check deadlineNSecs!
|
||||||
|
|
||||||
|
now = QDeadlineTimer::current(timerType);
|
||||||
|
qint64 nsec = now.deadlineNSecs() + 4000000 * minResolution;
|
||||||
|
deadline.setPreciseDeadline(nsec / (1000 * 1000 * 1000),
|
||||||
|
nsec % (1000 * 1000 * 1000), timerType);
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(deadline.remainingTime() > (3 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTime() <= (4 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution));
|
||||||
|
QCOMPARE(deadline.deadline(), nsec / (1000 * 1000));
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QDeadlineTimer::expire()
|
||||||
|
{
|
||||||
|
QFETCH_GLOBAL(Qt::TimerType, timerType);
|
||||||
|
|
||||||
|
QDeadlineTimer deadline(minResolution, timerType);
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
|
||||||
|
qint64 previousDeadline = deadline.deadlineNSecs();
|
||||||
|
|
||||||
|
QTest::qSleep(2 * minResolution);
|
||||||
|
|
||||||
|
QCOMPARE(deadline.remainingTime(), qint64(0));
|
||||||
|
QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
|
||||||
|
QVERIFY(deadline.deadline() != 0);
|
||||||
|
QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != 0);
|
||||||
|
QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
|
||||||
|
QCOMPARE(deadline.deadlineNSecs(), previousDeadline);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QDeadlineTimer::stdchrono()
|
||||||
|
{
|
||||||
|
#if !QT_HAS_INCLUDE(<chrono>)
|
||||||
|
QSKIP("std::chrono not found on this system");
|
||||||
|
#else
|
||||||
|
using namespace std::chrono;
|
||||||
|
QFETCH_GLOBAL(Qt::TimerType, timerType);
|
||||||
|
|
||||||
|
// create some forevers
|
||||||
|
QDeadlineTimer deadline = milliseconds::max();
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
deadline = milliseconds::max();
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
deadline.setRemainingTime(milliseconds::max(), timerType);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
deadline = nanoseconds::max();
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
deadline.setRemainingTime(nanoseconds::max(), timerType);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
deadline = hours::max();
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
deadline.setRemainingTime(hours::max(), timerType);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
|
||||||
|
deadline = time_point<system_clock>::max();
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
deadline.setDeadline(time_point<system_clock>::max(), timerType);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
deadline = time_point<steady_clock>::max();
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
deadline.setDeadline(time_point<steady_clock>::max(), timerType);
|
||||||
|
QVERIFY(deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
|
||||||
|
QVERIFY(deadline == time_point<steady_clock>::max());
|
||||||
|
QVERIFY(deadline == time_point<system_clock>::max());
|
||||||
|
QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::max());
|
||||||
|
|
||||||
|
// make it expired
|
||||||
|
deadline = time_point<system_clock>();
|
||||||
|
QVERIFY(deadline.hasExpired());
|
||||||
|
deadline.setDeadline(time_point<system_clock>(), timerType);
|
||||||
|
QVERIFY(deadline.hasExpired());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
deadline = time_point<steady_clock>();
|
||||||
|
QVERIFY(deadline.hasExpired());
|
||||||
|
deadline.setDeadline(time_point<steady_clock>(), timerType);
|
||||||
|
QVERIFY(deadline.hasExpired());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
|
||||||
|
QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::zero());
|
||||||
|
|
||||||
|
auto steady_before = steady_clock::now();
|
||||||
|
auto system_before = system_clock::now();
|
||||||
|
|
||||||
|
QTest::qSleep(minResolution);
|
||||||
|
auto now = QDeadlineTimer::current(timerType);
|
||||||
|
QTest::qSleep(minResolution);
|
||||||
|
|
||||||
|
auto steady_after = steady_clock::now();
|
||||||
|
auto system_after = system_clock::now();
|
||||||
|
|
||||||
|
{
|
||||||
|
auto diff = duration_cast<milliseconds>(steady_after - now.deadline<steady_clock>());
|
||||||
|
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
|
||||||
|
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
|
||||||
|
QDeadlineTimer dt_after(steady_after, timerType);
|
||||||
|
QVERIFY2(now < dt_after,
|
||||||
|
("now = " + QLocale().toString(now.deadlineNSecs()) +
|
||||||
|
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
|
||||||
|
|
||||||
|
diff = duration_cast<milliseconds>(now.deadline<steady_clock>() - steady_before);
|
||||||
|
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
|
||||||
|
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
|
||||||
|
QDeadlineTimer dt_before(steady_before, timerType);
|
||||||
|
QVERIFY2(now > dt_before,
|
||||||
|
("now = " + QLocale().toString(now.deadlineNSecs()) +
|
||||||
|
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto diff = duration_cast<milliseconds>(system_after - now.deadline<system_clock>());
|
||||||
|
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
|
||||||
|
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
|
||||||
|
QDeadlineTimer dt_after(system_after, timerType);
|
||||||
|
QVERIFY2(now < dt_after,
|
||||||
|
("now = " + QLocale().toString(now.deadlineNSecs()) +
|
||||||
|
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
|
||||||
|
|
||||||
|
diff = duration_cast<milliseconds>(now.deadline<system_clock>() - system_before);
|
||||||
|
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
|
||||||
|
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
|
||||||
|
QDeadlineTimer dt_before(system_before, timerType);
|
||||||
|
QVERIFY2(now > dt_before,
|
||||||
|
("now = " + QLocale().toString(now.deadlineNSecs()) +
|
||||||
|
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());
|
||||||
|
}
|
||||||
|
|
||||||
|
// make it regular
|
||||||
|
now = QDeadlineTimer::current(timerType);
|
||||||
|
deadline.setRemainingTime(milliseconds(4 * minResolution), timerType);
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() > milliseconds(3 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() < milliseconds(5 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() > nanoseconds(3000000 * minResolution));
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() < nanoseconds(5000000 * minResolution));
|
||||||
|
QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + milliseconds(3 * minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<steady_clock>() < (steady_clock::now() + milliseconds(5 * minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + milliseconds(3 * minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<system_clock>() < (system_clock::now() + milliseconds(5 * minResolution)));
|
||||||
|
if (timerType == Qt::CoarseTimer) {
|
||||||
|
QVERIFY(deadline > (now + milliseconds(3 * minResolution)));
|
||||||
|
QVERIFY(deadline < (now + milliseconds(5 * minResolution)));
|
||||||
|
QVERIFY(deadline > (now + nanoseconds(3000000 * minResolution)));
|
||||||
|
QVERIFY(deadline < (now + nanoseconds(5000000 * minResolution)));
|
||||||
|
QVERIFY(deadline > milliseconds(3 * minResolution));
|
||||||
|
QVERIFY(deadline < milliseconds(5 * minResolution));
|
||||||
|
QVERIFY(deadline > nanoseconds(3000000 * minResolution));
|
||||||
|
QVERIFY(deadline < nanoseconds(5000000 * minResolution));
|
||||||
|
QVERIFY(deadline >= steady_clock::now());
|
||||||
|
QVERIFY(deadline >= system_clock::now());
|
||||||
|
}
|
||||||
|
|
||||||
|
now = QDeadlineTimer::current(timerType);
|
||||||
|
deadline = QDeadlineTimer(seconds(1), timerType);
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() > (seconds(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() <= seconds(1));
|
||||||
|
QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + seconds(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + seconds(1) + milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + seconds(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + seconds(1) + milliseconds(minResolution)));
|
||||||
|
if (timerType == Qt::CoarseTimer) {
|
||||||
|
QVERIFY(deadline > (seconds(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline <= seconds(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
now = QDeadlineTimer::current(timerType);
|
||||||
|
deadline.setRemainingTime(hours(1), timerType);
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() > (hours(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() <= hours(1));
|
||||||
|
QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + hours(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + hours(1) + milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + hours(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + hours(1) + milliseconds(minResolution)));
|
||||||
|
|
||||||
|
now = QDeadlineTimer::current(timerType);
|
||||||
|
deadline.setDeadline(system_clock::now() + seconds(1), timerType);
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() > (seconds(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() <= seconds(1));
|
||||||
|
QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + seconds(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + seconds(1) + milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + seconds(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + seconds(1) + milliseconds(minResolution)));
|
||||||
|
|
||||||
|
now = QDeadlineTimer::current(timerType);
|
||||||
|
deadline.setDeadline(steady_clock::now() + seconds(1), timerType);
|
||||||
|
QVERIFY(!deadline.hasExpired());
|
||||||
|
QVERIFY(!deadline.isForever());
|
||||||
|
QCOMPARE(deadline.timerType(), timerType);
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() > (seconds(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.remainingTimeAsDuration() <= seconds(1));
|
||||||
|
QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + seconds(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + seconds(1) + milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + seconds(1) - milliseconds(minResolution)));
|
||||||
|
QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + seconds(1) + milliseconds(minResolution)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_QDeadlineTimer)
|
||||||
|
|
||||||
|
#include "tst_qdeadlinetimer.moc"
|
Loading…
x
Reference in New Issue
Block a user