diff options
Diffstat (limited to 'src/corelib/kernel/qeventdispatcher_unix.cpp')
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_unix.cpp | 163 |
1 files changed, 60 insertions, 103 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index c23fab2eef..21bd224415 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -1,50 +1,13 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// 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 "qplatformdefs.h" #include "qcoreapplication.h" -#include "qpair.h" +#include "qhash.h" #include "qsocketnotifier.h" #include "qthread.h" -#include "qelapsedtimer.h" #include "qeventdispatcher_unix_p.h" #include <private/qthread_p.h> @@ -55,23 +18,19 @@ #include <stdio.h> #include <stdlib.h> -#ifndef QT_NO_EVENTFD +#if __has_include(<sys/eventfd.h>) # include <sys/eventfd.h> +static constexpr bool UsingEventfd = true; +#else +static constexpr bool UsingEventfd = false; #endif -// VxWorks doesn't correctly set the _POSIX_... options #if defined(Q_OS_VXWORKS) -# if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK <= 0) -# undef _POSIX_MONOTONIC_CLOCK -# define _POSIX_MONOTONIC_CLOCK 1 -# endif # include <pipeDrv.h> -# include <sys/time.h> #endif -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED) -# include <sys/times.h> -#endif +using namespace std::chrono; +using namespace std::chrono_literals; QT_BEGIN_NAMESPACE @@ -91,11 +50,6 @@ static const char *socketType(QSocketNotifier::Type type) QThreadPipe::QThreadPipe() { - fds[0] = -1; - fds[1] = -1; -#if defined(Q_OS_VXWORKS) - name[0] = '\0'; -#endif } QThreadPipe::~QThreadPipe() @@ -103,7 +57,7 @@ QThreadPipe::~QThreadPipe() if (fds[0] >= 0) close(fds[0]); - if (fds[1] >= 0) + if (!UsingEventfd && fds[1] >= 0) close(fds[1]); #if defined(Q_OS_VXWORKS) @@ -140,23 +94,25 @@ bool QThreadPipe::init() // create the pipe if (pipeDevCreate(name, 128 /*maxMsg*/, 1 /*maxLength*/) != OK) { - perror("QThreadPipe: Unable to create thread pipe device %s", name); + perror("QThreadPipe: Unable to create thread pipe device"); return false; } if ((fds[0] = open(name, O_RDWR, 0)) < 0) { - perror("QThreadPipe: Unable to open pipe device %s", name); + perror("QThreadPipe: Unable to open pipe device"); return false; } initThreadPipeFD(fds[0]); fds[1] = fds[0]; #else -# ifndef QT_NO_EVENTFD - if ((fds[0] = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)) >= 0) - return true; + int ret; +# ifdef EFD_CLOEXEC + ret = fds[0] = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); # endif - if (qt_safe_pipe(fds, O_NONBLOCK) == -1) { + if (!UsingEventfd) + ret = qt_safe_pipe(fds, O_NONBLOCK); + if (ret == -1) { perror("QThreadPipe: Unable to create pipe"); return false; } @@ -172,15 +128,10 @@ pollfd QThreadPipe::prepare() const void QThreadPipe::wakeUp() { - if (wakeUps.testAndSetAcquire(0, 1)) { -#ifndef QT_NO_EVENTFD - if (fds[1] == -1) { - // eventfd - eventfd_t value = 1; - int ret; - EINTR_LOOP(ret, eventfd_write(fds[0], value)); - return; - } + if ((wakeUps.fetchAndOrAcquire(1) & 1) == 0) { +# ifdef EFD_CLOEXEC + eventfd_write(fds[0], 1); + return; #endif char c = 0; qt_safe_write(fds[1], &c, 1); @@ -201,14 +152,11 @@ int QThreadPipe::check(const pollfd &pfd) ::read(fds[0], c, sizeof(c)); ::ioctl(fds[0], FIOFLUSH, 0); #else -# ifndef QT_NO_EVENTFD - if (fds[1] == -1) { - // eventfd - eventfd_t value; - eventfd_read(fds[0], &value); - } else +# ifdef EFD_CLOEXEC + eventfd_t value; + eventfd_read(fds[0], &value); # endif - { + if (!UsingEventfd) { while (::read(fds[0], c, sizeof(c)) > 0) {} } #endif @@ -231,7 +179,7 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate() { // cleanup timers - qDeleteAll(timerList); + timerList.clearTimers(); } void QEventDispatcherUNIXPrivate::setSocketNotifierPending(QSocketNotifier *notifier) @@ -251,7 +199,7 @@ int QEventDispatcherUNIXPrivate::activateTimers() void QEventDispatcherUNIXPrivate::markPendingSocketNotifiers() { - for (const pollfd &pfd : qAsConst(pollfds)) { + for (const pollfd &pfd : std::as_const(pollfds)) { if (pfd.fd < 0 || pfd.revents == 0) continue; @@ -309,11 +257,11 @@ int QEventDispatcherUNIXPrivate::activateSocketNotifiers() } QEventDispatcherUNIX::QEventDispatcherUNIX(QObject *parent) - : QAbstractEventDispatcher(*new QEventDispatcherUNIXPrivate, parent) + : QAbstractEventDispatcherV2(*new QEventDispatcherUNIXPrivate, parent) { } QEventDispatcherUNIX::QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent) - : QAbstractEventDispatcher(dd, parent) + : QAbstractEventDispatcherV2(dd, parent) { } QEventDispatcherUNIX::~QEventDispatcherUNIX() @@ -322,10 +270,10 @@ QEventDispatcherUNIX::~QEventDispatcherUNIX() /*! \internal */ -void QEventDispatcherUNIX::registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *obj) +void QEventDispatcherUNIX::registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *obj) { #ifndef QT_NO_DEBUG - if (timerId < 1 || interval < 0 || !obj) { + if (qToUnderlying(timerId) < 1 || interval.count() < 0 || !obj) { qWarning("QEventDispatcherUNIX::registerTimer: invalid arguments"); return; } else if (obj->thread() != thread() || thread() != QThread::currentThread()) { @@ -341,10 +289,10 @@ void QEventDispatcherUNIX::registerTimer(int timerId, qint64 interval, Qt::Timer /*! \internal */ -bool QEventDispatcherUNIX::unregisterTimer(int timerId) +bool QEventDispatcherUNIX::unregisterTimer(Qt::TimerId timerId) { #ifndef QT_NO_DEBUG - if (timerId < 1) { + if (qToUnderlying(timerId) < 1) { qWarning("QEventDispatcherUNIX::unregisterTimer: invalid argument"); return false; } else if (thread() != QThread::currentThread()) { @@ -376,12 +324,12 @@ bool QEventDispatcherUNIX::unregisterTimers(QObject *object) return d->timerList.unregisterTimers(object); } -QList<QEventDispatcherUNIX::TimerInfo> -QEventDispatcherUNIX::registeredTimers(QObject *object) const +QList<QEventDispatcherUNIX::TimerInfoV2> +QEventDispatcherUNIX::timersForObject(QObject *object) const { if (!object) { qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument"); - return QList<TimerInfo>(); + return QList<TimerInfoV2>(); } Q_D(const QEventDispatcherUNIX); @@ -481,11 +429,19 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags) if (d->interrupt.loadRelaxed()) return false; - timespec *tm = nullptr; - timespec wait_tm = { 0, 0 }; - - if (!canWait || (include_timers && d->timerList.timerWait(wait_tm))) - tm = &wait_tm; + QDeadlineTimer deadline; + if (canWait) { + if (include_timers) { + std::optional<nanoseconds> remaining = d->timerList.timerWait(); + deadline = remaining ? QDeadlineTimer{*remaining} + : QDeadlineTimer(QDeadlineTimer::Forever); + } else { + deadline = QDeadlineTimer(QDeadlineTimer::Forever); + } + } else { + // Using the default-constructed `deadline`, which is already expired, + // ensures the code in the do-while loop in qt_safe_poll runs at least once. + } d->pollfds.clear(); d->pollfds.reserve(1 + (include_notifiers ? d->socketNotifiers.size() : 0)); @@ -498,10 +454,11 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags) d->pollfds.append(d->threadPipe.prepare()); int nevents = 0; - - switch (qt_safe_poll(d->pollfds.data(), d->pollfds.size(), tm)) { + switch (qt_safe_poll(d->pollfds.data(), d->pollfds.size(), deadline)) { case -1: - perror("qt_safe_poll"); + qErrnoWarning("qt_safe_poll"); + if (QT_CONFIG(poll_exit_on_error)) + abort(); break; case 0: break; @@ -519,17 +476,17 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags) return (nevents > 0); } -int QEventDispatcherUNIX::remainingTime(int timerId) +auto QEventDispatcherUNIX::remainingTime(Qt::TimerId timerId) const -> Duration { #ifndef QT_NO_DEBUG - if (timerId < 1) { + if (int(timerId) < 1) { qWarning("QEventDispatcherUNIX::remainingTime: invalid argument"); - return -1; + return Duration::min(); } #endif - Q_D(QEventDispatcherUNIX); - return d->timerList.timerRemainingTime(timerId); + Q_D(const QEventDispatcherUNIX); + return d->timerList.remainingDuration(timerId); } void QEventDispatcherUNIX::wakeUp() |