5#include "qplatformdefs.h"
13#include <private/qthread_p.h>
14#include <private/qcoreapplication_p.h>
15#include <private/qcore_unix_p.h>
21#if __has_include(<sys/eventfd.h>)
22# include <sys/eventfd.h>
28#if defined(Q_OS_VXWORKS)
32using namespace std::chrono;
33using namespace std::chrono_literals;
63#if defined(Q_OS_VXWORKS)
64 pipeDevDelete(
name,
true);
68#if defined(Q_OS_VXWORKS)
69static void initThreadPipeFD(
int fd)
71 int ret = fcntl(
fd, F_SETFD, FD_CLOEXEC);
73 perror(
"QEventDispatcherUNIXPrivate: Unable to init thread pipe");
77 perror(
"QEventDispatcherUNIXPrivate: Unable to get flags on thread pipe");
81 perror(
"QEventDispatcherUNIXPrivate: Unable to set flags on thread pipe");
89#elif defined(Q_OS_VXWORKS)
93 pipeDevDelete(
name,
true);
96 if (pipeDevCreate(
name, 128 , 1 ) != OK) {
97 perror(
"QThreadPipe: Unable to create thread pipe device");
102 perror(
"QThreadPipe: Unable to open pipe device");
106 initThreadPipeFD(
fds[0]);
111 ret =
fds[0] = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
116 perror(
"QThreadPipe: Unable to create pipe");
133 eventfd_write(
fds[0], 1);
146 const int readyread = pfd.revents & POLLIN;
151#if defined(Q_OS_VXWORKS)
153 ::ioctl(
fds[0], FIOFLUSH, 0);
166 qWarning(
"QThreadPipe: internal error, wakeUps.testAndSetRelease(1, 0) failed!");
176 qFatal(
"QEventDispatcherUNIXPrivate(): Cannot continue without a thread pipe");
202 for (
const pollfd &pfd : std::as_const(
pollfds)) {
203 if (pfd.fd < 0 || pfd.revents == 0)
211 static const struct {
220 for (
const auto &
n : notifiers) {
226 if (pfd.revents & POLLNVAL) {
227 qWarning(
"QSocketNotifier: Invalid socket %d with type %s, disabling...",
232 if (pfd.revents &
n.flags)
277 qWarning(
"QEventDispatcherUNIX::registerTimer: invalid arguments");
280 qWarning(
"QEventDispatcherUNIX::registerTimer: timers cannot be started from another thread");
286 d->timerList.registerTimer(timerId, interval, timerType,
obj);
296 qWarning(
"QEventDispatcherUNIX::unregisterTimer: invalid argument");
299 qWarning(
"QEventDispatcherUNIX::unregisterTimer: timers cannot be stopped from another thread");
305 return d->timerList.unregisterTimer(timerId);
315 qWarning(
"QEventDispatcherUNIX::unregisterTimers: invalid argument");
318 qWarning(
"QEventDispatcherUNIX::unregisterTimers: timers cannot be stopped from another thread");
324 return d->timerList.unregisterTimers(
object);
327QList<QEventDispatcherUNIX::TimerInfoV2>
331 qWarning(
"QEventDispatcherUNIX:registeredTimers: invalid argument");
332 return QList<TimerInfoV2>();
336 return d->timerList.registeredTimers(
object);
350 qWarning(
"QSocketNotifier: socket notifiers cannot be enabled from another thread");
359 qWarning(
"%s: Multiple socket notifiers for same socket %d and type %s",
372 qWarning(
"QSocketNotifier: socket notifier (fd %d) cannot be disabled from another thread.\n"
373 "(Notifier's thread is %s(%p), event dispatcher's thread is %s(%p), current thread is %s(%p))",
386 auto i =
d->socketNotifiers.find(sockfd);
387 if (
i ==
d->socketNotifiers.end())
392 if (sn_set.notifiers[
type] ==
nullptr)
396 qWarning(
"%s: Multiple socket notifiers for same socket %d and type %s",
401 sn_set.notifiers[
type] =
nullptr;
403 if (sn_set.isEmpty())
404 d->socketNotifiers.erase(
i);
410 d->interrupt.storeRelaxed(0);
415 auto threadData =
d->threadData.loadRelaxed();
422 const bool canWait = (threadData->canWaitLocked()
423 && !
d->interrupt.loadRelaxed()
429 if (
d->interrupt.loadRelaxed())
434 if (include_timers) {
435 std::optional<nanoseconds> remaining =
d->timerList.timerWait();
447 d->pollfds.reserve(1 + (include_notifiers ?
d->socketNotifiers.size() : 0));
449 if (include_notifiers)
454 d->pollfds.append(
d->threadPipe.prepare());
466 nevents +=
d->threadPipe.check(
d->pollfds.takeLast());
467 if (include_notifiers)
468 nevents +=
d->activateSocketNotifiers();
473 nevents +=
d->activateTimers();
476 return (nevents > 0);
482 if (
int(timerId) < 1) {
483 qWarning(
"QEventDispatcherUNIX::remainingTime: invalid argument");
484 return Duration::min();
489 return d->timerList.remainingDuration(timerId);
495 d->threadPipe.wakeUp();
501 d->interrupt.storeRelaxed(1);
507#include "moc_qeventdispatcher_unix_p.cpp"
DarwinBluetooth::LECBManagerNotifier * notifier
void aboutToBlock()
This signal is emitted before the event loop calls a function that could block.
std::chrono::nanoseconds Duration
A {std::chrono::duration} type that is used in various API in this class.
void awake()
This signal is emitted after the event loop returns from a function that could block.
T fetchAndOrAcquire(T valueToAdd) noexcept
bool testAndSetRelease(T expectedValue, T newValue) noexcept
static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data)
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static constexpr ForeverConstant Forever
void markPendingSocketNotifiers()
int activateSocketNotifiers()
QHash< int, QSocketNotifierSetUNIX > socketNotifiers
QList< QSocketNotifier * > pendingNotifiers
~QEventDispatcherUNIXPrivate()
void setSocketNotifierPending(QSocketNotifier *notifier)
QEventDispatcherUNIXPrivate()
QEventDispatcherUNIX(QObject *parent=nullptr)
Duration remainingTime(Qt::TimerId timerId) const override final
Returns the remaining time of the timer with the given timerId.
void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *object) override final
bool processEvents(QEventLoop::ProcessEventsFlags flags) override
Processes pending events that match flags until there are no more events to process.
void interrupt() final
Interrupts event dispatching.
void wakeUp() override
\threadsafe
void registerSocketNotifier(QSocketNotifier *notifier) final
Registers notifier with the event loop.
void unregisterSocketNotifier(QSocketNotifier *notifier) final
Unregisters notifier from the event dispatcher.
bool unregisterTimer(Qt::TimerId timerId) override final
QList< TimerInfoV2 > timersForObject(QObject *object) const override final
bool unregisterTimers(QObject *object) override final
iterator find(const Key &key)
Returns an iterator pointing to the item with the key in the hash.
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
bool isEmpty() const noexcept
QThread * thread() const
Returns the thread in which the object lives.
const_iterator cend() const noexcept
const_iterator cbegin() const noexcept
Type
This enum describes the various types of events that a socket notifier can recognize.
static QThread * currentThread()
EGLint EGLint EGLint EGLint int int int int * fds
QSet< QString >::iterator it
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt,...)
int qt_safe_poll(struct pollfd *fds, nfds_t nfds, QDeadlineTimer deadline)
static qint64 qt_safe_write(int fd, const void *data, qint64 len)
static struct pollfd qt_make_pollfd(int fd, short events)
static int qt_safe_pipe(int pipefd[2], int flags=0)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static constexpr bool UsingEventfd
static QT_BEGIN_NAMESPACE const char * socketType(QSocketNotifier::Type type)
#define QT_CONFIG(feature)
QT_BEGIN_NAMESPACE constexpr std::underlying_type_t< Enum > qToUnderlying(Enum e) noexcept
ReturnedValue read(const char *data)
file open(QIODevice::ReadOnly)
QDeadlineTimer deadline(30s)
bool contains(const AT &t) const noexcept
int check(const pollfd &pfd)