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 <oswald.buddenhagen@gmx.de>
bb10
parent
7715b186c7
commit
6dac45b246
|
|
@ -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<QSocketDescriptor>();
|
||||
qRegisterMetaType<QSocketNotifier::Type>();
|
||||
|
||||
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<QSocketDescriptor>();
|
||||
qRegisterMetaType<QSocketNotifier::Type>();
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ class tst_QSocketNotifier : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void constructing();
|
||||
void unexpectedDisconnection();
|
||||
void mixingWithTimers();
|
||||
#ifdef Q_OS_UNIX
|
||||
|
|
@ -85,6 +86,51 @@ static QHostAddress makeNonAny(const QHostAddress &address,
|
|||
return address;
|
||||
}
|
||||
|
||||
void tst_QSocketNotifier::constructing()
|
||||
{
|
||||
const qintptr fd = 15;
|
||||
|
||||
// Test constructing with no descriptor assigned.
|
||||
{
|
||||
QSocketNotifier notifier(QSocketNotifier::Read);
|
||||
|
||||
QVERIFY(!notifier.isValid());
|
||||
QCOMPARE(notifier.socket(), Q_INT64_C(-1));
|
||||
QCOMPARE(notifier.type(), QSocketNotifier::Read);
|
||||
QVERIFY(!notifier.isEnabled());
|
||||
|
||||
notifier.setEnabled(true);
|
||||
QVERIFY(!notifier.isEnabled());
|
||||
|
||||
notifier.setSocket(fd, true);
|
||||
QVERIFY(notifier.isValid());
|
||||
QCOMPARE(notifier.socket(), fd);
|
||||
QVERIFY(notifier.isEnabled());
|
||||
notifier.setEnabled(false);
|
||||
QVERIFY(!notifier.isEnabled());
|
||||
}
|
||||
|
||||
// Test constructing with the notifications enabled by default.
|
||||
{
|
||||
QSocketNotifier notifier(fd, QSocketNotifier::Write);
|
||||
|
||||
QVERIFY(notifier.isValid());
|
||||
QCOMPARE(notifier.socket(), fd);
|
||||
QCOMPARE(notifier.type(), QSocketNotifier::Write);
|
||||
QVERIFY(notifier.isEnabled());
|
||||
|
||||
notifier.setSocket(fd, false);
|
||||
QVERIFY(!notifier.isEnabled());
|
||||
|
||||
notifier.setEnabled(true);
|
||||
QVERIFY(notifier.isEnabled());
|
||||
notifier.setSocket(-1, true);
|
||||
QVERIFY(!notifier.isValid());
|
||||
QCOMPARE(notifier.socket(), Q_INT64_C(-1));
|
||||
QVERIFY(!notifier.isEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
class UnexpectedDisconnectTester : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
|||
Loading…
Reference in New Issue