diff options
Diffstat (limited to 'src/corelib/kernel/qeventdispatcher_glib.cpp')
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_glib.cpp | 162 |
1 files changed, 65 insertions, 97 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 92f3553247..1e906c4b27 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -1,55 +1,22 @@ -/**************************************************************************** -** -** 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 "qeventdispatcher_glib_p.h" #include "qeventdispatcher_unix_p.h" +#include <private/qnumeric_p.h> #include <private/qthread_p.h> #include "qcoreapplication.h" #include "qsocketnotifier.h" #include <QtCore/qlist.h> -#include <QtCore/qpair.h> #include <glib.h> +using namespace std::chrono; +using namespace std::chrono_literals; + QT_BEGIN_NAMESPACE struct GPollFDWithQSocketNotifier @@ -62,6 +29,7 @@ struct GSocketNotifierSource { GSource source; QList<GPollFDWithQSocketNotifier *> pollfds; + int activeNotifierPos; }; static gboolean socketNotifierSourcePrepare(GSource *, gint *timeout) @@ -76,12 +44,12 @@ static gboolean socketNotifierSourceCheck(GSource *source) GSocketNotifierSource *src = reinterpret_cast<GSocketNotifierSource *>(source); bool pending = false; - for (int i = 0; !pending && i < src->pollfds.count(); ++i) { + for (int i = 0; !pending && i < src->pollfds.size(); ++i) { GPollFDWithQSocketNotifier *p = src->pollfds.at(i); if (p->pollfd.revents & G_IO_NVAL) { // disable the invalid socket notifier - static const char *t[] = { "Read", "Write", "Exception" }; + const char * const t[] = { "Read", "Write", "Exception" }; qWarning("QSocketNotifier: Invalid socket %d and type '%s', disabling...", p->pollfd.fd, t[int(p->socketNotifier->type())]); // ### note, modifies src->pollfds! @@ -100,8 +68,9 @@ static gboolean socketNotifierSourceDispatch(GSource *source, GSourceFunc, gpoin QEvent event(QEvent::SockAct); GSocketNotifierSource *src = reinterpret_cast<GSocketNotifierSource *>(source); - for (int i = 0; i < src->pollfds.count(); ++i) { - GPollFDWithQSocketNotifier *p = src->pollfds.at(i); + for (src->activeNotifierPos = 0; src->activeNotifierPos < src->pollfds.size(); + ++src->activeNotifierPos) { + GPollFDWithQSocketNotifier *p = src->pollfds.at(src->activeNotifierPos); if ((p->pollfd.revents & p->pollfd.events) != 0) QCoreApplication::sendEvent(p->socketNotifier, &event); @@ -110,7 +79,7 @@ static gboolean socketNotifierSourceDispatch(GSource *source, GSourceFunc, gpoin return true; // ??? don't remove, right? } -static GSourceFuncs socketNotifierSourceFuncs = { +Q_CONSTINIT static GSourceFuncs socketNotifierSourceFuncs = { socketNotifierSourcePrepare, socketNotifierSourceCheck, socketNotifierSourceDispatch, @@ -129,11 +98,13 @@ struct GTimerSource static gboolean timerSourcePrepareHelper(GTimerSource *src, gint *timeout) { - timespec tv = { 0l, 0l }; - if (!(src->processEventsFlags & QEventLoop::X11ExcludeTimers) && src->timerList.timerWait(tv)) - *timeout = (tv.tv_sec * 1000) + ((tv.tv_nsec + 999999) / 1000 / 1000); - else + if (src->processEventsFlags & QEventLoop::X11ExcludeTimers) { *timeout = -1; + return true; + } + + auto remaining = src->timerList.timerWait().value_or(-1ms); + *timeout = qt_saturate<gint>(ceil<milliseconds>(remaining).count()); return (*timeout == 0); } @@ -144,10 +115,7 @@ static gboolean timerSourceCheckHelper(GTimerSource *src) || (src->processEventsFlags & QEventLoop::X11ExcludeTimers)) return false; - if (src->timerList.updateCurrentTime() < src->timerList.constFirst()->timeout) - return false; - - return true; + return !src->timerList.hasPendingTimers(); } static gboolean timerSourcePrepare(GSource *source, gint *timeout) @@ -184,7 +152,7 @@ static gboolean timerSourceDispatch(GSource *source, GSourceFunc, gpointer) return true; // ??? don't remove, right again? } -static GSourceFuncs timerSourceFuncs = { +Q_CONSTINIT static GSourceFuncs timerSourceFuncs = { timerSourcePrepare, timerSourceCheck, timerSourceDispatch, @@ -231,7 +199,7 @@ static gboolean idleTimerSourceDispatch(GSource *source, GSourceFunc, gpointer) return true; } -static GSourceFuncs idleTimerSourceFuncs = { +Q_CONSTINIT static GSourceFuncs idleTimerSourceFuncs = { idleTimerSourcePrepare, idleTimerSourceCheck, idleTimerSourceDispatch, @@ -279,7 +247,7 @@ static gboolean postEventSourceDispatch(GSource *s, GSourceFunc, gpointer) return true; // i dunno, george... } -static GSourceFuncs postEventSourceFuncs = { +Q_CONSTINIT static GSourceFuncs postEventSourceFuncs = { postEventSourcePrepare, postEventSourceCheck, postEventSourceDispatch, @@ -294,7 +262,7 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) { #if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 32 if (qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB")) { - static QBasicMutex mutex; + Q_CONSTINIT static QBasicMutex mutex; QMutexLocker locker(&mutex); if (!g_thread_supported()) g_thread_init(NULL); @@ -318,32 +286,36 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) #endif // setup post event source - postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs, - sizeof(GPostEventSource))); + GSource *source = g_source_new(&postEventSourceFuncs, sizeof(GPostEventSource)); + g_source_set_name(source, "[Qt] GPostEventSource"); + postEventSource = reinterpret_cast<GPostEventSource *>(source); + postEventSource->serialNumber.storeRelaxed(1); postEventSource->d = this; g_source_set_can_recurse(&postEventSource->source, true); g_source_attach(&postEventSource->source, mainContext); // setup socketNotifierSource - socketNotifierSource = - reinterpret_cast<GSocketNotifierSource *>(g_source_new(&socketNotifierSourceFuncs, - sizeof(GSocketNotifierSource))); + source = g_source_new(&socketNotifierSourceFuncs, sizeof(GSocketNotifierSource)); + g_source_set_name(source, "[Qt] GSocketNotifierSource"); + socketNotifierSource = reinterpret_cast<GSocketNotifierSource *>(source); (void) new (&socketNotifierSource->pollfds) QList<GPollFDWithQSocketNotifier *>(); g_source_set_can_recurse(&socketNotifierSource->source, true); g_source_attach(&socketNotifierSource->source, mainContext); // setup normal and idle timer sources - timerSource = reinterpret_cast<GTimerSource *>(g_source_new(&timerSourceFuncs, - sizeof(GTimerSource))); + source = g_source_new(&timerSourceFuncs, sizeof(GTimerSource)); + g_source_set_name(source, "[Qt] GTimerSource"); + timerSource = reinterpret_cast<GTimerSource *>(source); (void) new (&timerSource->timerList) QTimerInfoList(); timerSource->processEventsFlags = QEventLoop::AllEvents; timerSource->runWithIdlePriority = false; g_source_set_can_recurse(&timerSource->source, true); g_source_attach(&timerSource->source, mainContext); - idleTimerSource = reinterpret_cast<GIdleTimerSource *>(g_source_new(&idleTimerSourceFuncs, - sizeof(GIdleTimerSource))); + source = g_source_new(&idleTimerSourceFuncs, sizeof(GIdleTimerSource)); + g_source_set_name(source, "[Qt] GIdleTimerSource"); + idleTimerSource = reinterpret_cast<GIdleTimerSource *>(source); idleTimerSource->timerSource = timerSource; g_source_set_can_recurse(&idleTimerSource->source, true); g_source_attach(&idleTimerSource->source, mainContext); @@ -355,12 +327,12 @@ void QEventDispatcherGlibPrivate::runTimersOnceWithNormalPriority() } QEventDispatcherGlib::QEventDispatcherGlib(QObject *parent) - : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate), parent) + : QAbstractEventDispatcherV2(*(new QEventDispatcherGlibPrivate), parent) { } QEventDispatcherGlib::QEventDispatcherGlib(GMainContext *mainContext, QObject *parent) - : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate(mainContext)), parent) + : QAbstractEventDispatcherV2(*(new QEventDispatcherGlibPrivate(mainContext)), parent) { } QEventDispatcherGlib::~QEventDispatcherGlib() @@ -368,7 +340,7 @@ QEventDispatcherGlib::~QEventDispatcherGlib() Q_D(QEventDispatcherGlib); // destroy all timer sources - qDeleteAll(d->timerSource->timerList); + d->timerSource->timerList.clearTimers(); d->timerSource->timerList.~QTimerInfoList(); g_source_destroy(&d->timerSource->source); g_source_unref(&d->timerSource->source); @@ -378,7 +350,7 @@ QEventDispatcherGlib::~QEventDispatcherGlib() d->idleTimerSource = nullptr; // destroy socket notifier source - for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) { + for (int i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) { GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds[i]; g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd); delete p; @@ -405,7 +377,7 @@ bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags) { Q_D(QEventDispatcherGlib); - const bool canWait = (flags & QEventLoop::WaitForMoreEvents); + const bool canWait = flags.testAnyFlag(QEventLoop::WaitForMoreEvents); if (canWait) emit aboutToBlock(); else @@ -432,16 +404,10 @@ bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags) return result; } -bool QEventDispatcherGlib::hasPendingEvents() -{ - Q_D(QEventDispatcherGlib); - return g_main_context_pending(d->mainContext); -} - void QEventDispatcherGlib::registerSocketNotifier(QSocketNotifier *notifier) { Q_ASSERT(notifier); - int sockfd = notifier->socket(); + int sockfd = int(notifier->socket()); int type = notifier->type(); #ifndef QT_NO_DEBUG if (sockfd < 0) { @@ -481,8 +447,7 @@ void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier) { Q_ASSERT(notifier); #ifndef QT_NO_DEBUG - int sockfd = notifier->socket(); - if (sockfd < 0) { + if (notifier->socket() < 0) { qWarning("QSocketNotifier: Internal error"); return; } else if (notifier->thread() != thread() @@ -494,7 +459,7 @@ void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier) Q_D(QEventDispatcherGlib); - for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) { + for (int i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) { GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds.at(i); if (p->socketNotifier == notifier) { // found it @@ -503,15 +468,20 @@ void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier) d->socketNotifierSource->pollfds.removeAt(i); delete p; + // Keep a position in the list for the next item. + if (i <= d->socketNotifierSource->activeNotifierPos) + --d->socketNotifierSource->activeNotifierPos; + return; } } } -void QEventDispatcherGlib::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) +void QEventDispatcherGlib::registerTimer(Qt::TimerId timerId, Duration interval, + Qt::TimerType timerType, QObject *object) { #ifndef QT_NO_DEBUG - if (timerId < 1 || interval < 0 || !object) { + if (qToUnderlying(timerId) < 1 || interval < 0ns || !object) { qWarning("QEventDispatcherGlib::registerTimer: invalid arguments"); return; } else if (object->thread() != thread() || thread() != QThread::currentThread()) { @@ -524,10 +494,10 @@ void QEventDispatcherGlib::registerTimer(int timerId, int interval, Qt::TimerTyp d->timerSource->timerList.registerTimer(timerId, interval, timerType, object); } -bool QEventDispatcherGlib::unregisterTimer(int timerId) +bool QEventDispatcherGlib::unregisterTimer(Qt::TimerId timerId) { #ifndef QT_NO_DEBUG - if (timerId < 1) { + if (qToUnderlying(timerId) < 1) { qWarning("QEventDispatcherGlib::unregisterTimer: invalid argument"); return false; } else if (thread() != QThread::currentThread()) { @@ -556,28 +526,30 @@ bool QEventDispatcherGlib::unregisterTimers(QObject *object) return d->timerSource->timerList.unregisterTimers(object); } -QList<QEventDispatcherGlib::TimerInfo> QEventDispatcherGlib::registeredTimers(QObject *object) const +QList<QEventDispatcherGlib::TimerInfoV2> QEventDispatcherGlib::timersForObject(QObject *object) const { +#ifndef QT_NO_DEBUG if (!object) { - qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument"); - return QList<TimerInfo>(); + qWarning("QEventDispatcherGlib:timersForObject: invalid argument"); + return {}; } +#endif Q_D(const QEventDispatcherGlib); return d->timerSource->timerList.registeredTimers(object); } -int QEventDispatcherGlib::remainingTime(int timerId) +QEventDispatcherGlib::Duration QEventDispatcherGlib::remainingTime(Qt::TimerId timerId) const { #ifndef QT_NO_DEBUG - if (timerId < 1) { + if (qToUnderlying(timerId) < 1) { qWarning("QEventDispatcherGlib::remainingTimeTime: invalid argument"); - return -1; + return Duration::min(); } #endif - Q_D(QEventDispatcherGlib); - return d->timerSource->timerList.timerRemainingTime(timerId); + Q_D(const QEventDispatcherGlib); + return d->timerSource->timerList.remainingDuration(timerId); } void QEventDispatcherGlib::interrupt() @@ -592,10 +564,6 @@ void QEventDispatcherGlib::wakeUp() g_main_context_wakeup(d->mainContext); } -void QEventDispatcherGlib::flush() -{ -} - bool QEventDispatcherGlib::versionSupported() { #if !defined(GLIB_MAJOR_VERSION) || !defined(GLIB_MINOR_VERSION) || !defined(GLIB_MICRO_VERSION) @@ -606,7 +574,7 @@ bool QEventDispatcherGlib::versionSupported() } QEventDispatcherGlib::QEventDispatcherGlib(QEventDispatcherGlibPrivate &dd, QObject *parent) - : QAbstractEventDispatcher(dd, parent) + : QAbstractEventDispatcherV2(dd, parent) { } |