QElapsedTimer: rewrite using std::chrono::steady_clock everywhere

This commit deletes the direct, low-level functionality that
QElapsedTimer has carried since it was introduced. Everything now uses
only std::chrono::steady_clock and std::chrono::nanoseconds.

QDeadlineTimer temporarily still uses qt_gettime(), which is moved to
qcore_unix.cpp.

Task-number: QTBUG-110059
Change-Id: Ieec322d73c1e40ad95c8fffd174641a469b1eee5
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Thiago Macieira 2023-02-22 13:08:05 -08:00
parent 13f0ee021e
commit c9f4c0d45e
11 changed files with 297 additions and 464 deletions

View File

@ -512,7 +512,6 @@ qt_internal_extend_target(Core CONDITION WIN32
io/qwindowspipewriter.cpp io/qwindowspipewriter_p.h
io/qntdll_p.h
kernel/qcoreapplication_win.cpp
kernel/qelapsedtimer_win.cpp
kernel/qeventdispatcher_win.cpp kernel/qeventdispatcher_win_p.h
kernel/qfunctions_win.cpp kernel/qfunctions_win_p.h kernel/qfunctions_winrt_p.h
ipc/qsharedmemory_win.cpp
@ -972,11 +971,6 @@ qt_internal_extend_target(Core CONDITION APPLE AND NOT MACOS
${FWMobileCoreServices}
)
qt_internal_extend_target(Core CONDITION UNIX
SOURCES
kernel/qelapsedtimer_unix.cpp
)
qt_internal_extend_target(Core CONDITION ANDROID
SOURCES
io/qstandardpaths_android.cpp

View File

@ -65,6 +65,34 @@ int qt_open64(const char *pathname, int flags, mode_t mode)
#ifndef QT_BOOTSTRAPPED
static inline void do_gettime(qint64 *sec, qint64 *frac)
{
timespec ts;
clockid_t clk = CLOCK_REALTIME;
#if defined(CLOCK_MONOTONIC_RAW)
clk = CLOCK_MONOTONIC_RAW;
#elif defined(CLOCK_MONOTONIC)
clk = CLOCK_MONOTONIC;
#endif
clock_gettime(clk, &ts);
*sec = ts.tv_sec;
*frac = ts.tv_nsec;
}
// also used in qeventdispatcher_unix.cpp
struct timespec qt_gettime() noexcept
{
qint64 sec, frac;
do_gettime(&sec, &frac);
timespec tv;
tv.tv_sec = sec;
tv.tv_nsec = frac;
return tv;
}
#if QT_CONFIG(poll_pollts)
# define ppoll pollts
#endif

View File

@ -5,6 +5,10 @@
#include "qdeadlinetimer_p.h"
#include "private/qnumeric_p.h"
#ifdef Q_OS_UNIX
# include "qcore_unix_p.h"
#endif
QT_BEGIN_NAMESPACE
QT_IMPL_METATYPE_EXTERN(QDeadlineTimer)
@ -836,6 +840,23 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) noexcep
The QDeadlineTimer object will be constructed with the specified \a timerType.
*/
QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
{
QDeadlineTimer result;
#ifdef Q_OS_UNIX
static_assert(QDeadlineTimerNanosecondsInT2);
timespec ts = qt_gettime();
result.t1 = ts.tv_sec;
result.t2 = ts.tv_nsec;
#else
// ensure we get nanoseconds; this will work so long as steady_clock's
// time_point isn't of finer resolution (picoseconds)
std::chrono::nanoseconds ns = std::chrono::steady_clock::now().time_since_epoch();
result.t1 = ns.count();
#endif
result.type = timerType;
return result;
}
/*!
\fn bool QDeadlineTimer::operator==(QDeadlineTimer d1, QDeadlineTimer d2)

View File

@ -165,9 +165,219 @@ QT_BEGIN_NAMESPACE
function will return false.
*/
/*!
\fn QElapsedTimer::clockType() noexcept
Returns the clock type that this QElapsedTimer implementation uses.
Since Qt 6.6, QElapsedTimer uses \c{std::chrono::steady_clock}, so the
clock type is always \l MonotonicClock.
\sa isMonotonic()
*/
QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
{
// we use std::chrono::steady_clock
return MonotonicClock;
}
/*!
\fn QElapsedTimer::isMonotonic() noexcept
Returns \c true if this is a monotonic clock, false otherwise. See the
information on the different clock types to understand which ones are
monotonic.
Since Qt 6.6, QElapsedTimer uses \c{std::chrono::steady_clock}, so this
function now always returns true.
\sa clockType(), QElapsedTimer::ClockType
*/
bool QElapsedTimer::isMonotonic() noexcept
{
// We trust std::chrono::steady_clock to be steady (monotonic); if the
// Standard Library is lying to us, users must complain to their vendor.
return true;
}
/*!
Starts this timer. Once started, a timer value can be checked with elapsed() or msecsSinceReference().
Normally, a timer is started just before a lengthy operation, such as:
\snippet qelapsedtimer/main.cpp 0
Also, starting a timer makes it valid again.
\sa restart(), invalidate(), elapsed()
*/
void QElapsedTimer::start() noexcept
{
static_assert(sizeof(t1) == sizeof(Duration::rep));
// This assignment will work so long as TimePoint uses the same time
// duration or one of finer granularity than steady_clock::time_point. That
// means it will work until the first steady_clock using picoseconds.
TimePoint now = std::chrono::steady_clock::now();
t1 = now.time_since_epoch().count();
QT6_ONLY(t2 = 0);
}
/*!
Restarts the timer and returns the number of milliseconds elapsed since
the previous start.
This function is equivalent to obtaining the elapsed time with elapsed()
and then starting the timer again with start(), but it does so in one
single operation, avoiding the need to obtain the clock value twice.
Calling this function on a QElapsedTimer that is invalid
results in undefined behavior.
The following example illustrates how to use this function to calibrate a
parameter to a slow operation (for example, an iteration count) so that
this operation takes at least 250 milliseconds:
\snippet qelapsedtimer/main.cpp 3
\sa start(), invalidate(), elapsed(), isValid()
*/
qint64 QElapsedTimer::restart() noexcept
{
QElapsedTimer old = *this;
start();
return old.msecsTo(*this);
}
/*!
\since 6.6
Returns a \c{std::chrono::nanoseconds} with the time since this QElapsedTimer was last
started.
Calling this function on a QElapsedTimer that is invalid
results in undefined behavior.
On platforms that do not provide nanosecond resolution, the value returned
will be the best estimate available.
\sa start(), restart(), hasExpired(), invalidate()
*/
auto QElapsedTimer::durationElapsed() const noexcept -> Duration
{
TimePoint then{Duration(t1)};
return std::chrono::steady_clock::now() - then;
}
/*!
\since 4.8
Returns the number of nanoseconds since this QElapsedTimer was last
started.
Calling this function on a QElapsedTimer that is invalid
results in undefined behavior.
On platforms that do not provide nanosecond resolution, the value returned
will be the best estimate available.
\sa start(), restart(), hasExpired(), invalidate()
*/
qint64 QElapsedTimer::nsecsElapsed() const noexcept
{
return durationElapsed().count();
}
/*!
Returns the number of milliseconds since this QElapsedTimer was last
started.
Calling this function on a QElapsedTimer that is invalid
results in undefined behavior.
\sa start(), restart(), hasExpired(), isValid(), invalidate()
*/
qint64 QElapsedTimer::elapsed() const noexcept
{
using namespace std::chrono;
return duration_cast<milliseconds>(durationElapsed()).count();
}
/*!
Returns the number of milliseconds between last time this QElapsedTimer
object was started and its reference clock's start.
This number is usually arbitrary for all clocks except the
QElapsedTimer::SystemTime clock. For that clock type, this number is the
number of milliseconds since January 1st, 1970 at 0:00 UTC (that is, it
is the Unix time expressed in milliseconds).
On Linux, Windows and Apple platforms, this value is usually the time
since the system boot, though it usually does not include the time the
system has spent in sleep states.
\sa clockType(), elapsed()
*/
qint64 QElapsedTimer::msecsSinceReference() const noexcept
{
using namespace std::chrono;
return duration_cast<milliseconds>(Duration(t1)).count();
}
/*!
\since 6.6
Returns the time difference between this QElapsedTimer and \a other as a
\c{std::chrono::nanoseconds}. If \a other was started before this object,
the returned value will be negative. If it was started later, the returned
value will be positive.
The return value is undefined if this object or \a other were invalidated.
\sa secsTo(), elapsed()
*/
auto QElapsedTimer::durationTo(const QElapsedTimer &other) const noexcept -> Duration
{
Duration d1(t1);
Duration d2(other.t1);
return d2 - d1;
}
/*!
Returns the number of milliseconds between this QElapsedTimer and \a
other. If \a other was started before this object, the returned value
will be negative. If it was started later, the returned value will be
positive.
The return value is undefined if this object or \a other were invalidated.
\sa secsTo(), elapsed()
*/
qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
{
using namespace std::chrono;
return duration_cast<milliseconds>(durationTo(other)).count();
}
/*!
Returns the number of seconds between this QElapsedTimer and \a other. If
\a other was started before this object, the returned value will be
negative. If it was started later, the returned value will be positive.
Calling this function on or with a QElapsedTimer that is invalid
results in undefined behavior.
\sa msecsTo(), elapsed()
*/
qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
{
using namespace std::chrono;
return duration_cast<seconds>(durationTo(other)).count();
}
static const qint64 invalidData = Q_INT64_C(0x8000000000000000);
/*!
\fn QElapsedTimer::invalidate() noexcept
Marks this QElapsedTimer object as invalid.
An invalid object can be checked with isValid(). Calculations of timer
@ -207,4 +417,9 @@ bool QElapsedTimer::hasExpired(qint64 timeout) const noexcept
return quint64(elapsed()) > quint64(timeout);
}
bool operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
{
return lhs.t1 < rhs.t1;
}
QT_END_NAMESPACE

View File

@ -6,8 +6,9 @@
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
#include <chrono>
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QElapsedTimer
{
@ -21,6 +22,10 @@ public:
PerformanceCounter
};
// similar to std::chrono::*_clock
using Duration = std::chrono::nanoseconds;
using TimePoint = std::chrono::time_point<std::chrono::steady_clock, Duration>;
constexpr QElapsedTimer() = default;
static ClockType clockType() noexcept;
@ -31,11 +36,13 @@ public:
void invalidate() noexcept;
bool isValid() const noexcept;
Duration durationElapsed() const noexcept;
qint64 nsecsElapsed() const noexcept;
qint64 elapsed() const noexcept;
bool hasExpired(qint64 timeout) const noexcept;
qint64 msecsSinceReference() const noexcept;
Duration durationTo(const QElapsedTimer &other) const noexcept;
qint64 msecsTo(const QElapsedTimer &other) const noexcept;
qint64 secsTo(const QElapsedTimer &other) const noexcept;

View File

@ -1,169 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qelapsedtimer.h"
#include "qdeadlinetimer.h"
#include "qdatetime.h"
QT_BEGIN_NAMESPACE
/*!
Returns the clock type that this QElapsedTimer implementation uses.
\sa isMonotonic()
*/
QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
{
return SystemTime;
}
/*!
Returns \c true if this is a monotonic clock, false otherwise. See the
information on the different clock types to understand which ones are
monotonic.
\sa clockType(), QElapsedTimer::ClockType
*/
bool QElapsedTimer::isMonotonic() noexcept
{
return false;
}
/*!
Starts this timer. Once started, a timer value can be checked with elapsed() or msecsSinceReference().
Normally, a timer is started just before a lengthy operation, such as:
\snippet qelapsedtimer/main.cpp 0
Also, starting a timer makes it valid again.
\sa restart(), invalidate(), elapsed()
*/
void QElapsedTimer::start() noexcept
{
restart();
}
/*!
Restarts the timer and returns the number of milliseconds elapsed since
the previous start.
This function is equivalent to obtaining the elapsed time with elapsed()
and then starting the timer again with start(), but it does so in one
single operation, avoiding the need to obtain the clock value twice.
Calling this function on a QElapsedTimer that is invalid
results in undefined behavior.
The following example illustrates how to use this function to calibrate a
parameter to a slow operation (for example, an iteration count) so that
this operation takes at least 250 milliseconds:
\snippet qelapsedtimer/main.cpp 3
\sa start(), invalidate(), elapsed(), isValid()
*/
qint64 QElapsedTimer::restart() noexcept
{
qint64 old = t1;
t1 = QDateTime::currentMSecsSinceEpoch();
t2 = 0;
return t1 - old;
}
/*! \since 4.8
Returns the number of nanoseconds since this QElapsedTimer was last
started.
Calling this function on a QElapsedTimer that is invalid
results in undefined behavior.
On platforms that do not provide nanosecond resolution, the value returned
will be the best estimate available.
\sa start(), restart(), hasExpired(), invalidate()
*/
qint64 QElapsedTimer::nsecsElapsed() const noexcept
{
return elapsed() * 1000000;
}
/*!
Returns the number of milliseconds since this QElapsedTimer was last
started.
Calling this function on a QElapsedTimer that is invalid
results in undefined behavior.
\sa start(), restart(), hasExpired(), isValid(), invalidate()
*/
qint64 QElapsedTimer::elapsed() const noexcept
{
return QDateTime::currentMSecsSinceEpoch() - t1;
}
/*!
Returns the number of milliseconds between last time this QElapsedTimer
object was started and its reference clock's start.
This number is usually arbitrary for all clocks except the
QElapsedTimer::SystemTime clock. For that clock type, this number is the
number of milliseconds since January 1st, 1970 at 0:00 UTC (that is, it
is the Unix time expressed in milliseconds).
On Linux, Windows and Apple platforms, this value is usually the time
since the system boot, though it usually does not include the time the
system has spent in sleep states.
\sa clockType(), elapsed()
*/
qint64 QElapsedTimer::msecsSinceReference() const noexcept
{
return t1;
}
/*!
Returns the number of milliseconds between this QElapsedTimer and \a
other. If \a other was started before this object, the returned value
will be negative. If it was started later, the returned value will be
positive.
The return value is undefined if this object or \a other were invalidated.
\sa secsTo(), elapsed()
*/
qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
{
qint64 diff = other.t1 - t1;
return diff;
}
/*!
Returns the number of seconds between this QElapsedTimer and \a other. If
\a other was started before this object, the returned value will be
negative. If it was started later, the returned value will be positive.
Calling this function on or with a QElapsedTimer that is invalid
results in undefined behavior.
\sa msecsTo(), elapsed()
*/
qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
{
return msecsTo(other) / 1000;
}
bool operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
{
return lhs.t1 < rhs.t1;
}
QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
{
QDeadlineTimer result;
result.t1 = QDateTime::currentMSecsSinceEpoch() * 1000 * 1000;
result.type = timerType;
return result;
}
QT_END_NAMESPACE

View File

@ -1,160 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2016 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qelapsedtimer.h"
#include "qdeadlinetimer.h"
#include "qdeadlinetimer_p.h"
#if defined(Q_OS_VXWORKS)
#include "qfunctions_vxworks.h"
#else
#include <sys/time.h>
#include <time.h>
#endif
#include <unistd.h>
#include <qatomic.h>
#include "private/qcore_unix_p.h"
#if defined(QT_NO_CLOCK_MONOTONIC) || defined(QT_BOOTSTRAPPED)
// turn off the monotonic clock
# ifdef _POSIX_MONOTONIC_CLOCK
# undef _POSIX_MONOTONIC_CLOCK
# endif
# define _POSIX_MONOTONIC_CLOCK -1
#endif
QT_BEGIN_NAMESPACE
/*
* Design:
*
* POSIX offers a facility to select the system's monotonic clock when getting
* the current timestamp. Whereas the functions are mandatory in POSIX.1-2008,
* the presence of a monotonic clock is a POSIX Option (see the document
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_01_06 )
*
* The macro _POSIX_MONOTONIC_CLOCK can therefore assume the following values:
* -1 monotonic clock is never supported on this system
* 0 monotonic clock might be supported, runtime check is needed
* >1 (such as 200809L) monotonic clock is always supported
*
* Since Qt 6.6, we no longer perform any runtime checks and instead enforce
* the use of the monotonic clock in all OSes that have the CLOCK_MONOTONIC
* macro and use of the POSIX realtime clock functions.
*
* Conforming to:
* POSIX.1b-1993 section "Clocks and Timers"
* included in UNIX98 (Single Unix Specification v2)
* included in POSIX.1-2001
* see http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html
*/
static constexpr clockid_t regularClock()
{
#ifdef CLOCK_MONOTONIC
return CLOCK_MONOTONIC;
#else
return CLOCK_REALTIME;
#endif
}
bool QElapsedTimer::isMonotonic() noexcept
{
return clockType() == MonotonicClock;
}
QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
{
return regularClock() == CLOCK_REALTIME ? SystemTime : MonotonicClock;
}
static inline void do_gettime(qint64 *sec, qint64 *frac)
{
timespec ts;
clock_gettime(regularClock(), &ts);
*sec = ts.tv_sec;
*frac = ts.tv_nsec;
}
// used in qcore_unix.cpp and qeventdispatcher_unix.cpp
struct timespec qt_gettime() noexcept
{
qint64 sec, frac;
do_gettime(&sec, &frac);
timespec tv;
tv.tv_sec = sec;
tv.tv_nsec = frac;
return tv;
}
static qint64 elapsedAndRestart(qint64 sec, qint64 frac,
qint64 *nowsec, qint64 *nowfrac)
{
do_gettime(nowsec, nowfrac);
sec = *nowsec - sec;
frac = *nowfrac - frac;
return (sec * Q_INT64_C(1000000000) + frac) / Q_INT64_C(1000000);
}
void QElapsedTimer::start() noexcept
{
do_gettime(&t1, &t2);
}
qint64 QElapsedTimer::restart() noexcept
{
return elapsedAndRestart(t1, t2, &t1, &t2);
}
qint64 QElapsedTimer::nsecsElapsed() const noexcept
{
qint64 sec, frac;
do_gettime(&sec, &frac);
sec = sec - t1;
frac = frac - t2;
return sec * Q_INT64_C(1000000000) + frac;
}
qint64 QElapsedTimer::elapsed() const noexcept
{
return nsecsElapsed() / Q_INT64_C(1000000);
}
qint64 QElapsedTimer::msecsSinceReference() const noexcept
{
return t1 * Q_INT64_C(1000) + t2 / Q_INT64_C(1000000);
}
qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
{
qint64 secs = other.t1 - t1;
qint64 fraction = other.t2 - t2;
return (secs * Q_INT64_C(1000000000) + fraction) / Q_INT64_C(1000000);
}
qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
{
return other.t1 - t1;
}
bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept
{
return v1.t1 < v2.t1 || (v1.t1 == v2.t1 && v1.t2 < v2.t2);
}
QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
{
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

View File

@ -1,123 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qelapsedtimer.h"
#include "qdeadlinetimer.h"
#include "qdeadlinetimer_p.h"
#include <qt_windows.h>
QT_BEGIN_NAMESPACE
// Result of QueryPerformanceFrequency
static quint64 counterFrequency = 0;
static void resolveCounterFrequency()
{
static bool done = false;
if (done)
return;
// Retrieve the number of high-resolution performance counter ticks per second
LARGE_INTEGER frequency;
if (!QueryPerformanceFrequency(&frequency) || frequency.QuadPart == 0)
qFatal("QueryPerformanceFrequency failed, even though Microsoft documentation promises it wouldn't.");
counterFrequency = frequency.QuadPart;
done = true;
}
static inline qint64 ticksToNanoseconds(qint64 ticks)
{
// QueryPerformanceCounter uses an arbitrary frequency
qint64 seconds = ticks / counterFrequency;
qint64 nanoSeconds = (ticks - seconds * counterFrequency) * 1000000000 / counterFrequency;
return seconds * 1000000000 + nanoSeconds;
}
static quint64 getTickCount()
{
resolveCounterFrequency();
LARGE_INTEGER counter;
bool ok = QueryPerformanceCounter(&counter);
Q_ASSERT_X(ok, "QElapsedTimer::start()",
"QueryPerformanceCounter failed, although QueryPerformanceFrequency succeeded.");
Q_UNUSED(ok);
return counter.QuadPart;
}
quint64 qt_msectime()
{
return ticksToNanoseconds(getTickCount()) / 1000000;
}
QElapsedTimer::ClockType QElapsedTimer::clockType() noexcept
{
resolveCounterFrequency();
return PerformanceCounter;
}
bool QElapsedTimer::isMonotonic() noexcept
{
return true;
}
void QElapsedTimer::start() noexcept
{
t1 = getTickCount();
t2 = 0;
}
qint64 QElapsedTimer::restart() noexcept
{
qint64 oldt1 = t1;
t1 = getTickCount();
t2 = 0;
return ticksToNanoseconds(t1 - oldt1) / 1000000;
}
qint64 QElapsedTimer::nsecsElapsed() const noexcept
{
qint64 elapsed = getTickCount() - t1;
return ticksToNanoseconds(elapsed);
}
qint64 QElapsedTimer::elapsed() const noexcept
{
qint64 elapsed = getTickCount() - t1;
return ticksToNanoseconds(elapsed) / 1000000;
}
qint64 QElapsedTimer::msecsSinceReference() const noexcept
{
return ticksToNanoseconds(t1) / 1000000;
}
qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const noexcept
{
qint64 difference = other.t1 - t1;
return ticksToNanoseconds(difference) / 1000000;
}
qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const noexcept
{
return msecsTo(other) / 1000;
}
bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) noexcept
{
return (v1.t1 - v2.t1) < 0;
}
QDeadlineTimer QDeadlineTimer::current(Qt::TimerType timerType) noexcept
{
static_assert(!QDeadlineTimerNanosecondsInT2);
QDeadlineTimer result;
result.t1 = ticksToNanoseconds(getTickCount());
result.type = timerType;
return result;
}
QT_END_NAMESPACE

View File

@ -56,6 +56,13 @@ class QEventDispatcherWin32Private;
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
static quint64 qt_msectime()
{
using namespace std::chrono;
auto t = duration_cast<milliseconds>(steady_clock::now().time_since_epoch());
return t.count();
}
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
: interrupt(false), internalHwnd(0),
sendPostedEventsTimerId(0), wakeUps(0),

View File

@ -28,7 +28,6 @@ class QEventDispatcherWin32Private;
// forward declaration
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
quint64 qt_msectime();
class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher
{

View File

@ -1,8 +1,8 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QtCore/QDateTime>
#include <QtCore/QString>
#include <QtCore/QTime>
#include <QtCore/QElapsedTimer>
#include <QTest>
#include <QTimer>
@ -31,11 +31,25 @@ private Q_SLOTS:
void tst_QElapsedTimer::statics()
{
qDebug() << "Clock type is" << QElapsedTimer::clockType();
qDebug() << "Said clock is" << (QElapsedTimer::isMonotonic() ? "monotonic" : "not monotonic");
// these have been required since Qt 6.6
QCOMPARE(QElapsedTimer::clockType(), QElapsedTimer::MonotonicClock);
QVERIFY(QElapsedTimer::isMonotonic());
QElapsedTimer t;
t.start();
qDebug() << "Current time is" << t.msecsSinceReference();
qint64 system_now = QDateTime::currentMSecsSinceEpoch();
auto setprecision = +[](QTextStream &s) -> QTextStream & {
s.setRealNumberNotation(QTextStream::FixedNotation);
s.setRealNumberPrecision(3);
return s;
};
qDebug() << setprecision
<< "Current monotonic time is" << (t.msecsSinceReference() / 1000.)
<< "s and current system time is" << (system_now / 1000.) << 's';
if (qAbs(system_now - t.msecsSinceReference()) < 5 * minResolution)
qWarning() << "The monotonic clock is awfully close to the system clock"
" (it may not be monotonic at all!)";
}
void tst_QElapsedTimer::validity()