summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qabstracteventdispatcher.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qabstracteventdispatcher.cpp')
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp394
1 files changed, 277 insertions, 117 deletions
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
index 72504a178d..f3056a399c 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.cpp
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// 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 "qabstracteventdispatcher.h"
#include "qabstracteventdispatcher_p.h"
@@ -45,9 +9,12 @@
#include <private/qthread_p.h>
#include <private/qcoreapplication_p.h>
#include <private/qfreelist_p.h>
+#include <private/qnumeric_p.h>
QT_BEGIN_NAMESPACE
+using namespace std::chrono_literals;
+
// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
struct QtTimerIdFreeListConstants : public QFreeListDefaultConstants
{
@@ -68,15 +35,15 @@ enum {
Offset4 = 0x00010000,
Offset5 = 0x00100000,
- Size0 = Offset1 - Offset0,
- Size1 = Offset2 - Offset1,
- Size2 = Offset3 - Offset2,
- Size3 = Offset4 - Offset3,
- Size4 = Offset5 - Offset4,
+ Size0 = Offset1 - Offset0,
+ Size1 = Offset2 - Offset1,
+ Size2 = Offset3 - Offset2,
+ Size3 = Offset4 - Offset3,
+ Size4 = Offset5 - Offset4,
Size5 = QtTimerIdFreeListConstants::MaxIndex - Offset5
};
-const int QtTimerIdFreeListConstants::Sizes[QtTimerIdFreeListConstants::BlockCount] = {
+Q_CONSTINIT const int QtTimerIdFreeListConstants::Sizes[QtTimerIdFreeListConstants::BlockCount] = {
Size0,
Size1,
Size2,
@@ -88,6 +55,41 @@ const int QtTimerIdFreeListConstants::Sizes[QtTimerIdFreeListConstants::BlockCou
typedef QFreeList<void, QtTimerIdFreeListConstants> QtTimerIdFreeList;
Q_GLOBAL_STATIC(QtTimerIdFreeList, timerIdFreeList)
+template <typename T> static T fromDuration(std::chrono::nanoseconds interval)
+{
+ using namespace std::chrono;
+ qint64 value = ceil<milliseconds>(interval).count();
+ return qt_saturate<T>(value);
+}
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+static inline QAbstractEventDispatcherV2 *v2(QAbstractEventDispatcher *self)
+{
+ if (QAbstractEventDispatcherPrivate::get(self)->isV2)
+ return static_cast<QAbstractEventDispatcherV2 *>(self);
+ return nullptr;
+}
+
+static inline const QAbstractEventDispatcherV2 *v2(const QAbstractEventDispatcher *self)
+{
+ if (QAbstractEventDispatcherPrivate::get(self)->isV2)
+ return static_cast<const QAbstractEventDispatcherV2 *>(self);
+ return nullptr;
+}
+#endif // Qt 7
+
+QAbstractEventDispatcherPrivate::QAbstractEventDispatcherPrivate()
+{
+ // Create the timer ID free list here to make sure that it is destroyed
+ // after any global static thread that may be using it.
+ // See also QTBUG-58732.
+ if (!timerIdFreeList.isDestroyed())
+ (void)timerIdFreeList();
+}
+
+QAbstractEventDispatcherPrivate::~QAbstractEventDispatcherPrivate()
+ = default;
+
int QAbstractEventDispatcherPrivate::allocateTimerId()
{
// This function may be called after timerIdFreeList() has been destructed
@@ -145,6 +147,15 @@ void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
\sa QEventLoop, QCoreApplication, QThread
*/
+/*!
+ \typedef QAbstractEventDispatcher::Duration
+
+ A \c{std::chrono::duration} type that is used in various API in this class.
+ This type exists to facilitate a possible transition to a higher or lower
+ granularity.
+
+ In all current platforms, it is \c nanoseconds.
+*/
/*!
Constructs a new event dispatcher with the given \a parent.
@@ -210,8 +221,6 @@ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
\b{Note:} This function does not process events continuously; it
returns after all available events are processed.
-
- \sa hasPendingEvents()
*/
/*!
@@ -223,14 +232,6 @@ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
events. For timers and system level events, the situation is unknown.
*/
-/*! \fn bool QAbstractEventDispatcher::hasPendingEvents()
- \deprecated
-
- Returns \c true if there is an event waiting; otherwise returns false. This
- function is an implementation detail for
- QCoreApplication::hasPendingEvents() and must not be called directly.
-*/
-
/*!
\fn void QAbstractEventDispatcher::registerSocketNotifier(QSocketNotifier *notifier)
@@ -248,36 +249,41 @@ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
*/
/*!
- \obsolete
-
- \fn int QAbstractEventDispatcher::registerTimer(int interval, QObject *object)
+ \obsolete [6.8] This function will be removed in Qt 7. Use the overload taking \l Duration.
- Registers a timer with the specified \a interval for the given \a object
- and returns the timer id.
+ Registers a timer with the specified \a interval and \a timerType for the
+ given \a object and returns the timer id.
*/
+int QAbstractEventDispatcher::registerTimer(qint64 interval, Qt::TimerType timerType, QObject *object)
+{
+ return int(registerTimer(interval * 1ms, timerType, object));
+}
/*!
- \obsolete
-
- \fn void QAbstractEventDispatcher::registerTimer(int timerId, int interval, QObject *object)
-
- Register a timer with the specified \a timerId and \a interval for the
- given \a object.
-*/
+ \since 6.8
+ \overload
-/*!
Registers a timer with the specified \a interval and \a timerType for the
given \a object and returns the timer id.
*/
-int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerType, QObject *object)
+Qt::TimerId QAbstractEventDispatcher::registerTimer(Duration interval, Qt::TimerType timerType,
+ QObject *object)
{
- int id = QAbstractEventDispatcherPrivate::allocateTimerId();
+ auto id = Qt::TimerId(QAbstractEventDispatcherPrivate::allocateTimerId());
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ if (QAbstractEventDispatcherV2 *self = v2(this))
+ self->registerTimer(id, interval, timerType, object);
+ else
+ registerTimer(qToUnderlying(id), fromDuration<qint64>(interval), timerType, object);
+#else
registerTimer(id, interval, timerType, object);
+#endif
return id;
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
/*!
- \fn void QAbstractEventDispatcher::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
+ \fn void QAbstractEventDispatcher::registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object)
Register a timer with the specified \a timerId, \a interval, and \a
timerType for the given \a object.
@@ -293,15 +299,6 @@ int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerTyp
*/
/*!
- \fn bool QAbstractEventDispatcher::unregisterTimers(QObject *object)
-
- Unregisters all the timers associated with the given \a object.
- Returns \c true if all timers were successful removed; otherwise returns \c false.
-
- \sa unregisterTimer(), registeredTimers()
-*/
-
-/*!
\fn QList<TimerInfo> QAbstractEventDispatcher::registeredTimers(QObject *object) const
Returns a list of registered timers for \a object. The TimerInfo struct has
@@ -319,6 +316,57 @@ int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerTyp
\sa Qt::TimerType
*/
+#else // Qt 7
+/*!
+ \fn void QAbstractEventDispatcher::registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *object)
+ \since 6.8
+
+ Register a timer with the specified \a timerId, \a interval, and \a
+ timerType for the given \a object.
+
+ \sa unregisterTimer(), timersForObject()
+*/
+
+/*!
+ \fn bool QAbstractEventDispatcher::unregisterTimer(Qt::TimerId timerId)
+ \since 6.8
+
+ Unregisters the timer with the given \a timerId.
+ Returns \c true if successful; otherwise returns \c false.
+
+ \sa registerTimer(), unregisterTimers()
+*/
+
+/*!
+ \fn QList<TimerInfoV2> QAbstractEventDispatcher::timersForObject(QObject *object) const
+ \since 6.8
+
+ Returns a list of registered timers for \a object. The TimerInfoV2 struct has
+ \c timerId, \c interval, and \c timerType members.
+
+ \sa Qt::TimerType, registerTimer(), unregisterTimer()
+*/
+
+/*!
+ \fn QAbstractEventDispatcher::remainingTime(Qt::TimerId timerId) const
+
+ Returns the remaining time of the timer with the given \a timerId.
+ If the timer is inactive, the returned value will be negative. If the timer
+ is overdue, the returned value will be 0.
+
+ \sa Qt::TimerType, registerTimer(), unregisterTimer()
+*/
+#endif
+
+/*!
+ \fn bool QAbstractEventDispatcher::unregisterTimers(QObject *object)
+
+ Unregisters all the timers associated with the given \a object. Returns \c
+ true if all timers were successfully removed; otherwise returns \c false.
+
+ \sa unregisterTimer(), registeredTimers()
+*/
+
/*! \fn void QAbstractEventDispatcher::wakeUp()
\threadsafe
@@ -344,13 +392,6 @@ int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerTyp
return from processEvents() as soon as possible.
*/
-/*! \fn void QAbstractEventDispatcher::flush()
- \deprecated
-
- Depending from the event dispatcher implementation does nothing or
- calls QApplication::sendPostedEvents().
-*/
-
// ### DOC: Are these called when the _application_ starts/stops or just
// when the current _event loop_ starts/stops?
/*!
@@ -367,6 +408,7 @@ void QAbstractEventDispatcher::closingDown()
/*!
\class QAbstractEventDispatcher::TimerInfo
+ \deprecated [6.8] Use TimerInfoV2
\inmodule QtCore
This struct represents information about a timer:
@@ -374,7 +416,7 @@ void QAbstractEventDispatcher::closingDown()
\l{QAbstractEventDispatcher::TimerInfo::interval}{interval}, and
\l{QAbstractEventDispatcher::TimerInfo::timerType}{timerType}.
- \sa registeredTimers()
+ \sa registeredTimers(), QAbstractEventDispatcher::TimerInfoV2, timersForObject()
*/
/*! \fn QAbstractEventDispatcher::TimerInfo::TimerInfo(int timerId, int interval, Qt::TimerType timerType)
@@ -400,6 +442,37 @@ void QAbstractEventDispatcher::closingDown()
*/
/*!
+ \class QAbstractEventDispatcher::TimerInfoV2
+ \inmodule QtCore
+
+ This struct represents information about a timer:
+ \l{QAbstractEventDispatcher::TimerInfoV2::timerId}{timerId},
+ \l{QAbstractEventDispatcher::TimerInfoV2::interval}{interval}, and
+ \l{QAbstractEventDispatcher::TimerInfoV2::timerType}{timerType}.
+
+ \sa timersForObject()
+*/
+/*!
+ \variable QAbstractEventDispatcher::TimerInfoV2::timerId
+
+ The timer's unique id. This is created by registerTimer() upon creation and
+ uniquely identifies a timer while it is active. It is also used by
+ QTimer::id() and returned by QObject::startTimer().
+*/
+/*!
+ \variable QAbstractEventDispatcher::TimerInfoV2::interval
+
+ The timer's interval.
+*/
+/*!
+ \variable QAbstractEventDispatcher::TimerInfoV2::timerType
+
+ The timer's type
+
+ \sa Qt::TimerType
+*/
+
+/*!
Installs an event filter \a filterObj for all native events received by the application.
The event filter \a filterObj receives events via its \l {QAbstractNativeEventFilter::}{nativeEventFilter()}
@@ -450,7 +523,7 @@ void QAbstractEventDispatcher::installNativeEventFilter(QAbstractNativeEventFilt
void QAbstractEventDispatcher::removeNativeEventFilter(QAbstractNativeEventFilter *filter)
{
Q_D(QAbstractEventDispatcher);
- for (int i = 0; i < d->eventFilters.count(); ++i) {
+ for (int i = 0; i < d->eventFilters.size(); ++i) {
if (d->eventFilters.at(i) == filter) {
d->eventFilters[i] = nullptr;
break;
@@ -483,7 +556,7 @@ bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, vo
if (!d->eventFilters.isEmpty()) {
// Raise the loopLevel so that deleteLater() calls in or triggered
// by event_filter() will be processed from the main event loop.
- QScopedScopeLevelCounter scopeLevelCounter(d->threadData);
+ QScopedScopeLevelCounter scopeLevelCounter(d->threadData.loadAcquire());
for (int i = 0; i < d->eventFilters.size(); ++i) {
QAbstractNativeEventFilter *filter = d->eventFilters.at(i);
if (!filter)
@@ -495,54 +568,141 @@ bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, vo
return false;
}
-/*! \fn bool QAbstractEventDispatcher::filterEvent(void *message)
- \deprecated
+/*! \fn void QAbstractEventDispatcher::awake()
- Calls filterNativeEvent() with an empty eventType and \a message.
- This function returns \c true as soon as an
- event filter returns \c true, and false otherwise to indicate that
- the processing of the event should continue.
+ This signal is emitted after the event loop returns from a
+ function that could block.
+
+ \sa wakeUp(), aboutToBlock()
*/
-/*! \fn bool QAbstractEventDispatcher::registerEventNotifier(QWinEventNotifier *notifier)
+/*! \fn void QAbstractEventDispatcher::aboutToBlock()
- This pure virtual method exists on windows only and has to be reimplemented by a Windows specific
- event dispatcher implementation. \a notifier is the QWinEventNotifier instance to be registered.
+ This signal is emitted before the event loop calls a function that
+ could block.
- The method should return true if the registration of \a notifier was successful, otherwise false.
+ \sa awake()
+*/
- QWinEventNotifier calls this method in it's constructor and there should never be a need to call this
- method directly.
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+void QAbstractEventDispatcher::registerTimer(Qt::TimerId timerId, Duration interval,
+ Qt::TimerType timerType, QObject *object)
+{
+ if (QAbstractEventDispatcherV2 *self = v2(this))
+ self->registerTimer(timerId, interval, timerType, object);
+ else
+ registerTimer(int(timerId), fromDuration<qint64>(interval), timerType, object);
+}
- \sa QWinEventNotifier, unregisterEventNotifier()
-*/
+bool QAbstractEventDispatcher::unregisterTimer(Qt::TimerId timerId)
+{
+ if (QAbstractEventDispatcherV2 *self = v2(this))
+ return self->unregisterTimer(timerId);
+ return unregisterTimer(int(timerId));
+}
+
+QList<QAbstractEventDispatcher::TimerInfoV2>
+QAbstractEventDispatcher::timersForObject(QObject *object) const
+{
+ if (const QAbstractEventDispatcherV2 *self = v2(this))
+ return self->timersForObject(object);
+ QList<TimerInfo> timers = registeredTimers(object);
+ QList<TimerInfoV2> result;
+ result.reserve(timers.size());
+ for (const TimerInfo &t : timers)
+ result.emplaceBack(TimerInfoV2{ t.interval * 1ms, Qt::TimerId(t.timerId), t.timerType });
+ return result;
+}
-/*! \fn bool QAbstractEventDispatcher::unregisterEventNotifier(QWinEventNotifier *notifier)
+QAbstractEventDispatcher::Duration
+QAbstractEventDispatcher::remainingTime(Qt::TimerId timerId) const
+{
+ if (const QAbstractEventDispatcherV2 *self = v2(this))
+ return self->remainingTime(timerId);
+ return const_cast<QAbstractEventDispatcher *>(this)->remainingTime(int(timerId)) * 1ms;
+}
- This pure virtual method exists on windows only and has to be reimplemented by a Windows specific
- event dispatcher implementation. \a notifier is the QWinEventNotifier instance to be unregistered.
+/*!
+ \class QAbstractEventDispatcherV2
+ \inmodule QtCore
- QWinEventNotifier calls this method in it's destructor and there should never be a need to call this
- method directly.
+ This class is a temporary hack to enable transition to an API based on
+ \c{std::chrono} for the Qt event dispatcher. In Qt 7, it will be merged
+ with QAbstractEventDispatcher, replacing the pure virtuals there with the
+ ones defined here.
- \sa QWinEventNotifier, registerEventNotifier()
+ It is recommended applications and libraries port to the new API before
+ that future release to simplify work when the time comes.
*/
-/*! \fn void QAbstractEventDispatcher::awake()
+/*!
+ Constructs a new event dispatcher with the given \a parent.
+*/
+QAbstractEventDispatcherV2::QAbstractEventDispatcherV2(QObject *parent)
+ : QAbstractEventDispatcherV2(*new QAbstractEventDispatcherPrivate, parent)
+{
+}
- This signal is emitted after the event loop returns from a
- function that could block.
+/*!
+ \internal
+*/
+QAbstractEventDispatcherV2::QAbstractEventDispatcherV2(QAbstractEventDispatcherPrivate &dd,
+ QObject *parent)
+ : QAbstractEventDispatcher((dd.isV2 = true, dd), parent)
+{
+}
- \sa wakeUp(), aboutToBlock()
+/*!
+ Destroys the event dispatcher.
*/
+QAbstractEventDispatcherV2::~QAbstractEventDispatcherV2() = default;
-/*! \fn void QAbstractEventDispatcher::aboutToBlock()
+/*!
+ \internal
+ Temporary compatibility override.
+*/
+void QAbstractEventDispatcherV2::registerTimer(int timerId, qint64 interval,
+ Qt::TimerType timerType, QObject *object)
+{
+ auto self = static_cast<QAbstractEventDispatcherV2 *>(this);
+ self->registerTimer(Qt::TimerId(timerId), interval * 1ms, timerType, object);
+}
- This signal is emitted before the event loop calls a function that
- could block.
+/*!
+ \internal
+ Temporary compatibility override.
+*/
+bool QAbstractEventDispatcherV2::unregisterTimer(int timerId)
+{
+ auto self = static_cast<QAbstractEventDispatcherV2 *>(this);
+ return self->unregisterTimer(Qt::TimerId(timerId));
+}
- \sa awake()
+/*!
+ \internal
+ Temporary compatibility override.
*/
+auto QAbstractEventDispatcherV2::registeredTimers(QObject *object) const -> QList<TimerInfo>
+{
+ auto self = static_cast<const QAbstractEventDispatcherV2 *>(this);
+ QList<TimerInfoV2> timers = self->timersForObject(object);
+ QList<TimerInfo> result;
+ result.reserve(timers.size());
+ for (const TimerInfoV2 &t : timers)
+ result.emplaceBack(qToUnderlying(t.timerId), fromDuration<int>(t.interval), t.timerType);
+ return result;
+}
+
+/*!
+ \internal
+ Temporary compatibility override.
+*/
+int QAbstractEventDispatcherV2::remainingTime(int timerId)
+{
+ auto self = static_cast<QAbstractEventDispatcherV2 *>(this);
+ return fromDuration<int>(self->remainingTime(Qt::TimerId(timerId)));
+}
+#endif // ! Qt 7
QT_END_NAMESPACE