From 6dac45b24647aba4f5274e3908fc7bb661bcbef5 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Wed, 9 Dec 2020 20:54:00 +0200 Subject: QSocketNotifier: extend API to provide more flexible startup Technically, having a single constructor limits the use-cases for this class. We should take into account that: - an opened socket descriptor must be available at the moment of construction; - the constructor unconditionally enables the notifier (the possible solution notifier = new QSocketNotifier(...); notifier->setEnabled(false); is suboptimal due to heavy operations inside the event dispatcher); - for these reasons, QSocketNotifier most often cannot be a member of another class (we have an extra allocation and indirect access). This patch addresses this shortcoming by making it possible to set the socket descriptor at a later point: [ChangeLog][QtCore][QSocketNotifier] Added setSocket() and an additional constructor which requires no socket. Change-Id: I2eb2edf33ddafe99e528aac7d3774ade40795e7a Reviewed-by: Oswald Buddenhagen --- src/corelib/kernel/qsocketnotifier.cpp | 90 +++++++++++++++++++++++++++------- src/corelib/kernel/qsocketnotifier.h | 3 ++ 2 files changed, 76 insertions(+), 17 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp index 934727a6ba..0e360342e9 100644 --- a/src/corelib/kernel/qsocketnotifier.cpp +++ b/src/corelib/kernel/qsocketnotifier.cpp @@ -64,7 +64,7 @@ class QSocketNotifierPrivate : public QObjectPrivate public: QSocketDescriptor sockfd; QSocketNotifier::Type sntype; - bool snenabled; + bool snenabled = false; }; /*! @@ -85,11 +85,16 @@ public: Once you have opened a device using a low-level (usually platform-specific) API, you can create a socket notifier to - monitor the file descriptor. The socket notifier is enabled by - default, i.e. it emits the activated() signal whenever a socket - event corresponding to its type occurs. Connect the activated() - signal to the slot you want to be called when an event - corresponding to your socket notifier's type occurs. + monitor the file descriptor. If the descriptor is passed to the + notifier's constructor, the socket notifier is enabled by default, + i.e. it emits the activated() signal whenever a socket event + corresponding to its type occurs. Connect the activated() signal + to the slot you want to be called when an event corresponding to + your socket notifier's type occurs. + + You can create a socket notifier with no descriptor assigned. In + this case, you should call the setSocket() function after the + descriptor has been obtained. There are three types of socket notifiers: read, write, and exception. The type is described by the \l Type enum, and must be @@ -135,6 +140,29 @@ public: \sa QSocketNotifier(), type() */ +/*! + \since 6.1 + + Constructs a socket notifier with the given \a type that has no + descriptor assigned. The \a parent argument is passed to QObject's + constructor. + + Call the setSocket() function to set the descriptor for monitoring. + + \sa setSocket(), isValid(), isEnabled() +*/ + +QSocketNotifier::QSocketNotifier(Type type, QObject *parent) + : QObject(*new QSocketNotifierPrivate, parent) +{ + Q_D(QSocketNotifier); + + qRegisterMetaType(); + qRegisterMetaType(); + + d->sntype = type; +} + /*! Constructs a socket notifier with the given \a parent. It enables the \a socket, and watches for events of the given \a type. @@ -149,15 +177,11 @@ public: */ QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent) - : QObject(*new QSocketNotifierPrivate, parent) + : QSocketNotifier(type, parent) { Q_D(QSocketNotifier); - qRegisterMetaType(); - qRegisterMetaType(); - d->sockfd = socket; - d->sntype = type; d->snenabled = true; auto thisThreadData = d->threadData.loadRelaxed(); @@ -208,11 +232,29 @@ QSocketNotifier::~QSocketNotifier() \sa type(), socket() */ +/*! + \since 6.1 + + Assigns the \a socket to this notifier. The \a enable argument is + passed to the setEnabled() function. + + \sa setEnabled(), isValid() +*/ +void QSocketNotifier::setSocket(qintptr socket, bool enable) +{ + Q_D(QSocketNotifier); + + if (d->sockfd != QSocketDescriptor(socket)) { + setEnabled(false); + d->sockfd = socket; + } + setEnabled(enable); +} /*! - Returns the socket identifier specified to the constructor. + Returns the socket identifier assigned to this object. - \sa type() + \sa isValid(), type() */ qintptr QSocketNotifier::socket() const { @@ -231,6 +273,20 @@ QSocketNotifier::Type QSocketNotifier::type() const return d->sntype; } +/*! + \since 6.1 + + Returns \c true if the notifier is valid (that is, it has + a descriptor assigned); otherwise returns \c false. + + \sa setSocket() +*/ +bool QSocketNotifier::isValid() const +{ + Q_D(const QSocketNotifier); + return d->sockfd.isValid(); +} + /*! Returns \c true if the notifier is enabled; otherwise returns \c false. @@ -246,10 +302,10 @@ bool QSocketNotifier::isEnabled() const If \a enable is true, the notifier is enabled; otherwise the notifier is disabled. - The notifier is enabled by default, i.e. it emits the activated() - signal whenever a socket event corresponding to its - \l{type()}{type} occurs. If it is disabled, it ignores socket - events (the same effect as not creating the socket notifier). + When the notifier is enabled, it emits the activated() signal whenever + a socket event corresponding to its \l{type()}{type} occurs. When it is + disabled, it ignores socket events (the same effect as not creating + the socket notifier). Write notifiers should normally be disabled immediately after the activated() signal has been emitted diff --git a/src/corelib/kernel/qsocketnotifier.h b/src/corelib/kernel/qsocketnotifier.h index b8a5cc542a..fdf11961c3 100644 --- a/src/corelib/kernel/qsocketnotifier.h +++ b/src/corelib/kernel/qsocketnotifier.h @@ -54,12 +54,15 @@ class Q_CORE_EXPORT QSocketNotifier : public QObject public: enum Type { Read, Write, Exception }; + explicit QSocketNotifier(Type, QObject *parent = nullptr); QSocketNotifier(qintptr socket, Type, QObject *parent = nullptr); ~QSocketNotifier(); + void setSocket(qintptr socket, bool enable = false); qintptr socket() const; Type type() const; + bool isValid() const; bool isEnabled() const; public Q_SLOTS: -- cgit v1.2.3