summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/kernel.pri7
-rw-r--r--src/corelib/kernel/qelapsedtimer.cpp267
-rw-r--r--src/corelib/kernel/qelapsedtimer.h95
-rw-r--r--src/corelib/kernel/qelapsedtimer_generic.cpp204
-rw-r--r--src/corelib/kernel/qelapsedtimer_mac.cpp149
-rw-r--r--src/corelib/kernel/qelapsedtimer_unix.cpp251
-rw-r--r--src/corelib/kernel/qelapsedtimer_win.cpp164
7 files changed, 1137 insertions, 0 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 991b73812a..39fe61ea4e 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -4,6 +4,7 @@ HEADERS += \
kernel/qabstracteventdispatcher.h \
kernel/qabstractnativeeventfilter.h \
kernel/qbasictimer.h \
+ kernel/qelapsedtimer.h \
kernel/qeventloop.h\
kernel/qpointer.h \
kernel/qcorecmdlineargs_p.h \
@@ -45,6 +46,7 @@ SOURCES += \
kernel/qabstracteventdispatcher.cpp \
kernel/qabstractnativeeventfilter.cpp \
kernel/qbasictimer.cpp \
+ kernel/qelapsedtimer.cpp \
kernel/qeventloop.cpp \
kernel/qcoreapplication.cpp \
kernel/qcoreevent.cpp \
@@ -69,6 +71,7 @@ SOURCES += \
win32 {
SOURCES += \
kernel/qcoreapplication_win.cpp \
+ kernel/qelapsedtimer_win.cpp \
kernel/qwineventnotifier.cpp \
kernel/qsharedmemory_win.cpp \
kernel/qsystemsemaphore_win.cpp
@@ -103,6 +106,7 @@ mac {
kernel/qcoreapplication_mac.cpp \
kernel/qcore_mac.cpp \
kernel/qcore_foundation.mm
+ !nacl: SOURCES += kernel/qelapsedtimer_mac.cpp
OBJECTIVE_SOURCES += \
kernel/qcore_mac_objc.mm \
@@ -131,6 +135,7 @@ unix|integrity {
kernel/qcrashhandler.cpp \
kernel/qeventdispatcher_unix.cpp \
kernel/qtimerinfo_unix.cpp
+ !darwin|nacl: SOURCES += kernel/qelapsedtimer_unix.cpp
HEADERS += \
kernel/qcore_unix_p.h \
@@ -196,3 +201,5 @@ android {
kernel/qjnihelpers_p.h \
kernel/qjni_p.h
}
+
+!darwin:!unix:!win32: SOURCES += kernel/qelapsedtimer_generic.cpp
diff --git a/src/corelib/kernel/qelapsedtimer.cpp b/src/corelib/kernel/qelapsedtimer.cpp
new file mode 100644
index 0000000000..2eabb4c3a3
--- /dev/null
+++ b/src/corelib/kernel/qelapsedtimer.cpp
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include "qelapsedtimer.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QElapsedTimer
+ \inmodule QtCore
+ \brief The QElapsedTimer class provides a fast way to calculate elapsed times.
+ \since 4.7
+
+ \reentrant
+ \ingroup tools
+
+ The QElapsedTimer class is usually used to quickly calculate how much
+ time has elapsed between two events. Its API is similar to that of QTime,
+ so code that was using that can be ported quickly to the new class.
+
+ However, unlike QTime, QElapsedTimer tries to use monotonic clocks if
+ possible. This means it's not possible to convert QElapsedTimer objects
+ to a human-readable time.
+
+ The typical use-case for the class is to determine how much time was
+ spent in a slow operation. The simplest example of such a case is for
+ debugging purposes, as in the following example:
+
+ \snippet qelapsedtimer/main.cpp 0
+
+ In this example, the timer is started by a call to start() and the
+ elapsed timer is calculated by the elapsed() function.
+
+ The time elapsed can also be used to recalculate the time available for
+ another operation, after the first one is complete. This is useful when
+ the execution must complete within a certain time period, but several
+ steps are needed. The \tt{waitFor}-type functions in QIODevice and its
+ subclasses are good examples of such need. In that case, the code could
+ be as follows:
+
+ \snippet qelapsedtimer/main.cpp 1
+
+ Another use-case is to execute a certain operation for a specific
+ timeslice. For this, QElapsedTimer provides the hasExpired() convenience
+ function, which can be used to determine if a certain number of
+ milliseconds has already elapsed:
+
+ \snippet qelapsedtimer/main.cpp 2
+
+ \section1 Reference Clocks
+
+ QElapsedTimer will use the platform's monotonic reference clock in all
+ platforms that support it (see QElapsedTimer::isMonotonic()). This has
+ the added benefit that QElapsedTimer is immune to time adjustments, such
+ as the user correcting the time. Also unlike QTime, QElapsedTimer is
+ immune to changes in the timezone settings, such as daylight-saving
+ periods.
+
+ On the other hand, this means QElapsedTimer values can only be compared
+ with other values that use the same reference. This is especially true if
+ the time since the reference is extracted from the QElapsedTimer object
+ (QElapsedTimer::msecsSinceReference()) and serialised. These values
+ should never be exchanged across the network or saved to disk, since
+ there's no telling whether the computer node receiving the data is the
+ same as the one originating it or if it has rebooted since.
+
+ It is, however, possible to exchange the value with other processes
+ running on the same machine, provided that they also use the same
+ reference clock. QElapsedTimer will always use the same clock, so it's
+ safe to compare with the value coming from another process in the same
+ machine. If comparing to values produced by other APIs, you should check
+ that the clock used is the same as QElapsedTimer (see
+ QElapsedTimer::clockType()).
+
+ \section2 32-bit overflows
+
+ Some of the clocks used by QElapsedTimer have a limited range and may
+ overflow after hitting the upper limit (usually 32-bit). QElapsedTimer
+ deals with this overflow issue and presents a consistent timing. However,
+ when extracting the time since reference from QElapsedTimer, two
+ different processes in the same machine may have different understanding
+ of how much time has actually elapsed.
+
+ The information on which clocks types may overflow and how to remedy that
+ issue is documented along with the clock types.
+
+ \sa QTime, QTimer
+*/
+
+/*!
+ \enum QElapsedTimer::ClockType
+
+ This enum contains the different clock types that QElapsedTimer may use.
+
+ QElapsedTimer will always use the same clock type in a particular
+ machine, so this value will not change during the lifetime of a program.
+ It is provided so that QElapsedTimer can be used with other non-Qt
+ implementations, to guarantee that the same reference clock is being
+ used.
+
+ \value SystemTime The human-readable system time. This clock is not monotonic.
+ \value MonotonicClock The system's monotonic clock, usually found in Unix systems. This clock is monotonic and does not overflow.
+ \value TickCounter The system's tick counter, used on Windows systems. This clock may overflow.
+ \value MachAbsoluteTime The Mach kernel's absolute time (OS X and iOS). This clock is monotonic and does not overflow.
+ \value PerformanceCounter The high-resolution performance counter provided by Windows. This clock is monotonic and does not overflow.
+
+ \section2 SystemTime
+
+ The system time clock is purely the real time, expressed in milliseconds
+ since Jan 1, 1970 at 0:00 UTC. It's equivalent to the value returned by
+ the C and POSIX \tt{time} function, with the milliseconds added. This
+ clock type is currently only used on Unix systems that do not support
+ monotonic clocks (see below).
+
+ This is the only non-monotonic clock that QElapsedTimer may use.
+
+ \section2 MonotonicClock
+
+ This is the system's monotonic clock, expressed in milliseconds since an
+ arbitrary point in the past. This clock type is used on Unix systems
+ which support POSIX monotonic clocks (\tt{_POSIX_MONOTONIC_CLOCK}).
+
+ This clock does not overflow.
+
+ \section2 TickCounter
+
+ The tick counter clock type is based on the system's or the processor's
+ tick counter, multiplied by the duration of a tick. This clock type is
+ used on Windows platforms. If the high-precision performance
+ counter is available on Windows, the \tt{PerformanceCounter} clock type
+ is used instead.
+
+ The TickCounter clock type is the only clock type that may overflow.
+ Windows Vista and Windows Server 2008 support the extended 64-bit tick
+ counter, which allows avoiding the overflow.
+
+ On Windows systems, the clock overflows after 2^32 milliseconds, which
+ corresponds to roughly 49.7 days. This means two processes' reckoning of
+ the time since the reference may be different by multiples of 2^32
+ milliseconds. When comparing such values, it's recommended that the high
+ 32 bits of the millisecond count be masked off.
+
+ \section2 MachAbsoluteTime
+
+ This clock type is based on the absolute time presented by Mach kernels,
+ such as that found on OS X. This clock type is presented separately
+ from MonotonicClock since OS X and iOS are also Unix systems and may support
+ a POSIX monotonic clock with values differing from the Mach absolute
+ time.
+
+ This clock is monotonic and does not overflow.
+
+ \section2 PerformanceCounter
+
+ This clock uses the Windows functions \tt{QueryPerformanceCounter} and
+ \tt{QueryPerformanceFrequency} to access the system's high-precision
+ performance counter. Since this counter may not be available on all
+ systems, QElapsedTimer will fall back to the \tt{TickCounter} clock
+ automatically, if this clock cannot be used.
+
+ This clock is monotonic and does not overflow.
+
+ \sa clockType(), isMonotonic()
+*/
+
+/*!
+ \fn QElapsedTimer::QElapsedTimer()
+ \since 5.4
+
+ Constructs an invalid QElapsedTimer. A timer becomes valid once it has been
+ started.
+
+ \sa isValid(), start()
+*/
+
+
+/*!
+ \fn bool QElapsedTimer::operator ==(const QElapsedTimer &other) const
+
+ Returns \c true if this object and \a other contain the same time.
+*/
+
+/*!
+ \fn bool QElapsedTimer::operator !=(const QElapsedTimer &other) const
+
+ Returns \c true if this object and \a other contain different times.
+*/
+
+static const qint64 invalidData = Q_INT64_C(0x8000000000000000);
+
+/*!
+ Marks this QElapsedTimer object as invalid.
+
+ An invalid object can be checked with isValid(). Calculations of timer
+ elapsed since invalid data are undefined and will likely produce bizarre
+ results.
+
+ \sa isValid(), start(), restart()
+*/
+void QElapsedTimer::invalidate() Q_DECL_NOTHROW
+{
+ t1 = t2 = invalidData;
+}
+
+/*!
+ Returns \c false if the timer has never been started or invalidated by a
+ call to invalidate().
+
+ \sa invalidate(), start(), restart()
+*/
+bool QElapsedTimer::isValid() const Q_DECL_NOTHROW
+{
+ return t1 != invalidData && t2 != invalidData;
+}
+
+/*!
+ Returns \c true if this QElapsedTimer has already expired by \a timeout
+ milliseconds (that is, more than \a timeout milliseconds have elapsed).
+ 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.
+
+ \sa elapsed()
+*/
+bool QElapsedTimer::hasExpired(qint64 timeout) const Q_DECL_NOTHROW
+{
+ // if timeout is -1, quint64(timeout) is LLINT_MAX, so this will be
+ // considered as never expired
+ return quint64(elapsed()) > quint64(timeout);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qelapsedtimer.h b/src/corelib/kernel/qelapsedtimer.h
new file mode 100644
index 0000000000..7954b41bf4
--- /dev/null
+++ b/src/corelib/kernel/qelapsedtimer.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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 QELAPSEDTIMER_H
+#define QELAPSEDTIMER_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class Q_CORE_EXPORT QElapsedTimer
+{
+public:
+ enum ClockType {
+ SystemTime,
+ MonotonicClock,
+ TickCounter,
+ MachAbsoluteTime,
+ PerformanceCounter
+ };
+
+ Q_DECL_CONSTEXPR QElapsedTimer()
+ : t1(Q_INT64_C(0x8000000000000000)),
+ t2(Q_INT64_C(0x8000000000000000))
+ {
+ }
+
+ static ClockType clockType() Q_DECL_NOTHROW;
+ static bool isMonotonic() Q_DECL_NOTHROW;
+
+ void start() Q_DECL_NOTHROW;
+ qint64 restart() Q_DECL_NOTHROW;
+ void invalidate() Q_DECL_NOTHROW;
+ bool isValid() const Q_DECL_NOTHROW;
+
+ qint64 nsecsElapsed() const Q_DECL_NOTHROW;
+ qint64 elapsed() const Q_DECL_NOTHROW;
+ bool hasExpired(qint64 timeout) const Q_DECL_NOTHROW;
+
+ qint64 msecsSinceReference() const Q_DECL_NOTHROW;
+ qint64 msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW;
+ qint64 secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW;
+
+ bool operator==(const QElapsedTimer &other) const Q_DECL_NOTHROW
+ { return t1 == other.t1 && t2 == other.t2; }
+ bool operator!=(const QElapsedTimer &other) const Q_DECL_NOTHROW
+ { return !(*this == other); }
+
+ friend bool Q_CORE_EXPORT operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW;
+
+private:
+ qint64 t1;
+ qint64 t2;
+};
+
+QT_END_NAMESPACE
+
+#endif // QELAPSEDTIMER_H
diff --git a/src/corelib/kernel/qelapsedtimer_generic.cpp b/src/corelib/kernel/qelapsedtimer_generic.cpp
new file mode 100644
index 0000000000..8c724247be
--- /dev/null
+++ b/src/corelib/kernel/qelapsedtimer_generic.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include "qelapsedtimer.h"
+#include "qdatetime.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Returns the clock type that this QElapsedTimer implementation uses.
+
+ \sa isMonotonic()
+*/
+QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
+{
+ 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() Q_DECL_NOTHROW
+{
+ 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() Q_DECL_NOTHROW
+{
+ restart();
+}
+
+/*!
+ Restarts the timer and returns the time 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() Q_DECL_NOTHROW
+{
+ 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 Q_DECL_NOTHROW
+{
+ 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 Q_DECL_NOTHROW
+{
+ 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 OS X/iOS systems, 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 Q_DECL_NOTHROW
+{
+ 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 Q_DECL_NOTHROW
+{
+ 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 Q_DECL_NOTHROW
+{
+ return msecsTo(other) / 1000;
+}
+
+/*!
+ \relates QElapsedTimer
+
+ Returns \c true if \a v1 was started before \a v2, false otherwise.
+
+ The returned value is undefined if one of the two parameters is invalid
+ and the other isn't. However, two invalid timers are equal and thus this
+ function will return false.
+*/
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
+{
+ return v1.t1 < v2.t1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qelapsedtimer_mac.cpp b/src/corelib/kernel/qelapsedtimer_mac.cpp
new file mode 100644
index 0000000000..886e0f41b2
--- /dev/null
+++ b/src/corelib/kernel/qelapsedtimer_mac.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// ask for the latest POSIX, just in case
+#define _POSIX_C_SOURCE 200809L
+
+#include "qelapsedtimer.h"
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <mach/mach_time.h>
+#include <private/qcore_unix_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
+{
+ return MachAbsoluteTime;
+}
+
+bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW
+{
+ return true;
+}
+
+static mach_timebase_info_data_t info = {0,0};
+static qint64 absoluteToNSecs(qint64 cpuTime)
+{
+ if (info.denom == 0)
+ mach_timebase_info(&info);
+#ifdef __LP64__
+ __uint128_t nsecs = static_cast<__uint128_t>(cpuTime) * info.numer / info.denom;
+ return static_cast<qint64>(nsecs);
+#else
+ qint64 nsecs = cpuTime * info.numer / info.denom;
+ return nsecs;
+#endif
+}
+
+static qint64 absoluteToMSecs(qint64 cpuTime)
+{
+ return absoluteToNSecs(cpuTime) / 1000000;
+}
+
+timespec qt_gettime() Q_DECL_NOTHROW
+{
+ timespec tv;
+
+ uint64_t cpu_time = mach_absolute_time();
+ uint64_t nsecs = absoluteToNSecs(cpu_time);
+ tv.tv_sec = nsecs / 1000000000ull;
+ tv.tv_nsec = nsecs - (tv.tv_sec * 1000000000ull);
+ return tv;
+}
+
+void qt_nanosleep(timespec amount)
+{
+ // Mac doesn't have clock_nanosleep, but it does have nanosleep.
+ // nanosleep is POSIX.1-1993
+
+ int r;
+ EINTR_LOOP(r, nanosleep(&amount, &amount));
+}
+
+void QElapsedTimer::start() Q_DECL_NOTHROW
+{
+ t1 = mach_absolute_time();
+ t2 = 0;
+}
+
+qint64 QElapsedTimer::restart() Q_DECL_NOTHROW
+{
+ qint64 old = t1;
+ t1 = mach_absolute_time();
+ t2 = 0;
+
+ return absoluteToMSecs(t1 - old);
+}
+
+qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW
+{
+ uint64_t cpu_time = mach_absolute_time();
+ return absoluteToNSecs(cpu_time - t1);
+}
+
+qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW
+{
+ uint64_t cpu_time = mach_absolute_time();
+ return absoluteToMSecs(cpu_time - t1);
+}
+
+qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW
+{
+ return absoluteToMSecs(t1);
+}
+
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+{
+ return absoluteToMSecs(other.t1 - t1);
+}
+
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+{
+ return msecsTo(other) / 1000;
+}
+
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
+{
+ return v1.t1 < v2.t1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qelapsedtimer_unix.cpp b/src/corelib/kernel/qelapsedtimer_unix.cpp
new file mode 100644
index 0000000000..e2c3ae6280
--- /dev/null
+++ b/src/corelib/kernel/qelapsedtimer_unix.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Intel Corporation.
+** 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$
+**
+****************************************************************************/
+
+#include "qelapsedtimer.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
+ *
+ * The unixCheckClockType() function will return the clock to use: either
+ * CLOCK_MONOTONIC or CLOCK_REALTIME. In the case the POSIX option has a value
+ * of zero, then this function stores a static that contains the clock to be
+ * used.
+ *
+ * There's one extra case, which is when CLOCK_REALTIME isn't defined. When
+ * that's the case, we'll emulate the clock_gettime function with gettimeofday.
+ *
+ * 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
+ */
+
+#if !defined(CLOCK_REALTIME)
+# define CLOCK_REALTIME 0
+static inline void qt_clock_gettime(int, struct timespec *ts)
+{
+ // support clock_gettime with gettimeofday
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ ts->tv_sec = tv.tv_sec;
+ ts->tv_nsec = tv.tv_usec * 1000;
+}
+
+# ifdef _POSIX_MONOTONIC_CLOCK
+# undef _POSIX_MONOTONIC_CLOCK
+# define _POSIX_MONOTONIC_CLOCK -1
+# endif
+#else
+static inline void qt_clock_gettime(clockid_t clock, struct timespec *ts)
+{
+ clock_gettime(clock, ts);
+}
+#endif
+
+static int unixCheckClockType()
+{
+#ifdef Q_OS_LINUX
+ // Despite glibc claiming that we should check at runtime, the Linux kernel
+ // always supports the monotonic clock
+ return CLOCK_MONOTONIC;
+#elif (_POSIX_MONOTONIC_CLOCK-0 == 0) && defined(_SC_MONOTONIC_CLOCK)
+ // we need a value we can store in a clockid_t that isn't a valid clock
+ // check if the valid ones are both non-negative or both non-positive
+# if CLOCK_MONOTONIC >= 0 && CLOCK_REALTIME >= 0
+# define IS_VALID_CLOCK(clock) (clock >= 0)
+# define INVALID_CLOCK -1
+# elif CLOCK_MONOTONIC <= 0 && CLOCK_REALTIME <= 0
+# define IS_VALID_CLOCK(clock) (clock <= 0)
+# define INVALID_CLOCK 1
+# else
+# error "Sorry, your system has weird values for CLOCK_MONOTONIC and CLOCK_REALTIME"
+# endif
+
+ static QBasicAtomicInt clockToUse = Q_BASIC_ATOMIC_INITIALIZER(INVALID_CLOCK);
+ int clock = clockToUse.loadAcquire();
+ if (Q_LIKELY(IS_VALID_CLOCK(clock)))
+ return clock;
+
+ // detect if the system supports monotonic timers
+ clock = sysconf(_SC_MONOTONIC_CLOCK) > 0 ? CLOCK_MONOTONIC : CLOCK_REALTIME;
+ clockToUse.storeRelease(clock);
+ return clock;
+
+# undef INVALID_CLOCK
+# undef IS_VALID_CLOCK
+#elif (_POSIX_MONOTONIC_CLOCK-0) > 0
+ return CLOCK_MONOTONIC;
+#else
+ return CLOCK_REALTIME;
+#endif
+}
+
+bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW
+{
+ return clockType() == MonotonicClock;
+}
+
+QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
+{
+ return unixCheckClockType() == CLOCK_REALTIME ? SystemTime : MonotonicClock;
+}
+
+static inline void do_gettime(qint64 *sec, qint64 *frac)
+{
+ timespec ts;
+ qt_clock_gettime(unixCheckClockType(), &ts);
+ *sec = ts.tv_sec;
+ *frac = ts.tv_nsec;
+}
+
+// used in qcore_unix.cpp and qeventdispatcher_unix.cpp
+struct timespec qt_gettime() Q_DECL_NOTHROW
+{
+ qint64 sec, frac;
+ do_gettime(&sec, &frac);
+
+ timespec tv;
+ tv.tv_sec = sec;
+ tv.tv_nsec = frac;
+
+ return tv;
+}
+
+void qt_nanosleep(timespec amount)
+{
+ // We'd like to use clock_nanosleep.
+ //
+ // But clock_nanosleep is from POSIX.1-2001 and both are *not*
+ // affected by clock changes when using relative sleeps, even for
+ // CLOCK_REALTIME.
+ //
+ // nanosleep is POSIX.1-1993
+
+ int r;
+ EINTR_LOOP(r, nanosleep(&amount, &amount));
+}
+
+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() Q_DECL_NOTHROW
+{
+ do_gettime(&t1, &t2);
+}
+
+qint64 QElapsedTimer::restart() Q_DECL_NOTHROW
+{
+ return elapsedAndRestart(t1, t2, &t1, &t2);
+}
+
+qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW
+{
+ qint64 sec, frac;
+ do_gettime(&sec, &frac);
+ sec = sec - t1;
+ frac = frac - t2;
+ return sec * Q_INT64_C(1000000000) + frac;
+}
+
+qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW
+{
+ return nsecsElapsed() / Q_INT64_C(1000000);
+}
+
+qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW
+{
+ return t1 * Q_INT64_C(1000) + t2 / Q_INT64_C(1000000);
+}
+
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+{
+ 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 Q_DECL_NOTHROW
+{
+ return other.t1 - t1;
+}
+
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
+{
+ return v1.t1 < v2.t1 || (v1.t1 == v2.t1 && v1.t2 < v2.t2);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qelapsedtimer_win.cpp b/src/corelib/kernel/qelapsedtimer_win.cpp
new file mode 100644
index 0000000000..520126d262
--- /dev/null
+++ b/src/corelib/kernel/qelapsedtimer_win.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include "qelapsedtimer.h"
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+// Result of QueryPerformanceFrequency, 0 indicates that the high resolution timer is unavailable
+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)) {
+ qFatal("QueryPerformanceFrequency failed, even though Microsoft documentation promises it wouldn't.");
+ counterFrequency = 0;
+ } else {
+ counterFrequency = frequency.QuadPart;
+ }
+
+ done = true;
+}
+
+static inline qint64 ticksToNanoseconds(qint64 ticks)
+{
+ if (counterFrequency > 0) {
+ // QueryPerformanceCounter uses an arbitrary frequency
+ qint64 seconds = ticks / counterFrequency;
+ qint64 nanoSeconds = (ticks - seconds * counterFrequency) * 1000000000 / counterFrequency;
+ return seconds * 1000000000 + nanoSeconds;
+ } else {
+ // GetTickCount(64) return milliseconds
+ return ticks * 1000000;
+ }
+}
+
+static quint64 getTickCount()
+{
+ resolveCounterFrequency();
+
+ // This avoids a division by zero and disables the high performance counter if it's not available
+ if (counterFrequency > 0) {
+ LARGE_INTEGER counter;
+
+ bool ok = QueryPerformanceCounter(&counter);
+ Q_ASSERT_X(ok, "QElapsedTimer::start()",
+ "QueryPerformanceCounter failed, although QueryPerformanceFrequency succeeded.");
+ Q_UNUSED(ok);
+ return counter.QuadPart;
+ }
+
+ return GetTickCount64();
+}
+
+quint64 qt_msectime()
+{
+ return ticksToNanoseconds(getTickCount()) / 1000000;
+}
+
+QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
+{
+ resolveCounterFrequency();
+
+ if (counterFrequency > 0)
+ return PerformanceCounter;
+ else
+ return TickCounter;
+}
+
+bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW
+{
+ return true;
+}
+
+void QElapsedTimer::start() Q_DECL_NOTHROW
+{
+ t1 = getTickCount();
+ t2 = 0;
+}
+
+qint64 QElapsedTimer::restart() Q_DECL_NOTHROW
+{
+ qint64 oldt1 = t1;
+ t1 = getTickCount();
+ t2 = 0;
+ return ticksToNanoseconds(t1 - oldt1) / 1000000;
+}
+
+qint64 QElapsedTimer::nsecsElapsed() const Q_DECL_NOTHROW
+{
+ qint64 elapsed = getTickCount() - t1;
+ return ticksToNanoseconds(elapsed);
+}
+
+qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW
+{
+ qint64 elapsed = getTickCount() - t1;
+ return ticksToNanoseconds(elapsed) / 1000000;
+}
+
+qint64 QElapsedTimer::msecsSinceReference() const Q_DECL_NOTHROW
+{
+ return ticksToNanoseconds(t1) / 1000000;
+}
+
+qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+{
+ qint64 difference = other.t1 - t1;
+ return ticksToNanoseconds(difference) / 1000000;
+}
+
+qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const Q_DECL_NOTHROW
+{
+ return msecsTo(other) / 1000;
+}
+
+bool operator<(const QElapsedTimer &v1, const QElapsedTimer &v2) Q_DECL_NOTHROW
+{
+ return (v1.t1 - v2.t1) < 0;
+}
+
+QT_END_NAMESPACE