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:
parent
13f0ee021e
commit
c9f4c0d45e
@ -512,7 +512,6 @@ qt_internal_extend_target(Core CONDITION WIN32
|
|||||||
io/qwindowspipewriter.cpp io/qwindowspipewriter_p.h
|
io/qwindowspipewriter.cpp io/qwindowspipewriter_p.h
|
||||||
io/qntdll_p.h
|
io/qntdll_p.h
|
||||||
kernel/qcoreapplication_win.cpp
|
kernel/qcoreapplication_win.cpp
|
||||||
kernel/qelapsedtimer_win.cpp
|
|
||||||
kernel/qeventdispatcher_win.cpp kernel/qeventdispatcher_win_p.h
|
kernel/qeventdispatcher_win.cpp kernel/qeventdispatcher_win_p.h
|
||||||
kernel/qfunctions_win.cpp kernel/qfunctions_win_p.h kernel/qfunctions_winrt_p.h
|
kernel/qfunctions_win.cpp kernel/qfunctions_win_p.h kernel/qfunctions_winrt_p.h
|
||||||
ipc/qsharedmemory_win.cpp
|
ipc/qsharedmemory_win.cpp
|
||||||
@ -972,11 +971,6 @@ qt_internal_extend_target(Core CONDITION APPLE AND NOT MACOS
|
|||||||
${FWMobileCoreServices}
|
${FWMobileCoreServices}
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_internal_extend_target(Core CONDITION UNIX
|
|
||||||
SOURCES
|
|
||||||
kernel/qelapsedtimer_unix.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
qt_internal_extend_target(Core CONDITION ANDROID
|
qt_internal_extend_target(Core CONDITION ANDROID
|
||||||
SOURCES
|
SOURCES
|
||||||
io/qstandardpaths_android.cpp
|
io/qstandardpaths_android.cpp
|
||||||
|
@ -65,6 +65,34 @@ int qt_open64(const char *pathname, int flags, mode_t mode)
|
|||||||
|
|
||||||
#ifndef QT_BOOTSTRAPPED
|
#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)
|
#if QT_CONFIG(poll_pollts)
|
||||||
# define ppoll pollts
|
# define ppoll pollts
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
#include "qdeadlinetimer_p.h"
|
#include "qdeadlinetimer_p.h"
|
||||||
#include "private/qnumeric_p.h"
|
#include "private/qnumeric_p.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
# include "qcore_unix_p.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QT_IMPL_METATYPE_EXTERN(QDeadlineTimer)
|
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.
|
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)
|
\fn bool QDeadlineTimer::operator==(QDeadlineTimer d1, QDeadlineTimer d2)
|
||||||
|
@ -165,9 +165,219 @@ QT_BEGIN_NAMESPACE
|
|||||||
function will return false.
|
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);
|
static const qint64 invalidData = Q_INT64_C(0x8000000000000000);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
\fn QElapsedTimer::invalidate() noexcept
|
||||||
Marks this QElapsedTimer object as invalid.
|
Marks this QElapsedTimer object as invalid.
|
||||||
|
|
||||||
An invalid object can be checked with isValid(). Calculations of timer
|
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);
|
return quint64(elapsed()) > quint64(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
|
||||||
|
{
|
||||||
|
return lhs.t1 < rhs.t1;
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
|
|
||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
#include <chrono>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class Q_CORE_EXPORT QElapsedTimer
|
class Q_CORE_EXPORT QElapsedTimer
|
||||||
{
|
{
|
||||||
@ -21,6 +22,10 @@ public:
|
|||||||
PerformanceCounter
|
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;
|
constexpr QElapsedTimer() = default;
|
||||||
|
|
||||||
static ClockType clockType() noexcept;
|
static ClockType clockType() noexcept;
|
||||||
@ -31,11 +36,13 @@ public:
|
|||||||
void invalidate() noexcept;
|
void invalidate() noexcept;
|
||||||
bool isValid() const noexcept;
|
bool isValid() const noexcept;
|
||||||
|
|
||||||
|
Duration durationElapsed() const noexcept;
|
||||||
qint64 nsecsElapsed() const noexcept;
|
qint64 nsecsElapsed() const noexcept;
|
||||||
qint64 elapsed() const noexcept;
|
qint64 elapsed() const noexcept;
|
||||||
bool hasExpired(qint64 timeout) const noexcept;
|
bool hasExpired(qint64 timeout) const noexcept;
|
||||||
|
|
||||||
qint64 msecsSinceReference() const noexcept;
|
qint64 msecsSinceReference() const noexcept;
|
||||||
|
Duration durationTo(const QElapsedTimer &other) const noexcept;
|
||||||
qint64 msecsTo(const QElapsedTimer &other) const noexcept;
|
qint64 msecsTo(const QElapsedTimer &other) const noexcept;
|
||||||
qint64 secsTo(const QElapsedTimer &other) const noexcept;
|
qint64 secsTo(const QElapsedTimer &other) const noexcept;
|
||||||
|
|
||||||
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -56,6 +56,13 @@ class QEventDispatcherWin32Private;
|
|||||||
|
|
||||||
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
|
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()
|
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
|
||||||
: interrupt(false), internalHwnd(0),
|
: interrupt(false), internalHwnd(0),
|
||||||
sendPostedEventsTimerId(0), wakeUps(0),
|
sendPostedEventsTimerId(0), wakeUps(0),
|
||||||
|
@ -28,7 +28,6 @@ class QEventDispatcherWin32Private;
|
|||||||
|
|
||||||
// forward declaration
|
// forward declaration
|
||||||
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
|
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
|
class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher
|
||||||
{
|
{
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// Copyright (C) 2016 The Qt Company Ltd.
|
// Copyright (C) 2016 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// 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/QString>
|
||||||
#include <QtCore/QTime>
|
|
||||||
#include <QtCore/QElapsedTimer>
|
#include <QtCore/QElapsedTimer>
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@ -31,11 +31,25 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
void tst_QElapsedTimer::statics()
|
void tst_QElapsedTimer::statics()
|
||||||
{
|
{
|
||||||
qDebug() << "Clock type is" << QElapsedTimer::clockType();
|
// these have been required since Qt 6.6
|
||||||
qDebug() << "Said clock is" << (QElapsedTimer::isMonotonic() ? "monotonic" : "not monotonic");
|
QCOMPARE(QElapsedTimer::clockType(), QElapsedTimer::MonotonicClock);
|
||||||
|
QVERIFY(QElapsedTimer::isMonotonic());
|
||||||
|
|
||||||
QElapsedTimer t;
|
QElapsedTimer t;
|
||||||
t.start();
|
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()
|
void tst_QElapsedTimer::validity()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user