Rework toggling the state of read notifier on unbuffered socket
To avoid infinite loop on unbuffered socket, previous implementation always disabled the read notifications before emitting a readyRead() signal. So, it's very likely that the socket will toggle the state of notifier twice (on->off->on) in one notification cycle. This patch prevents this unnecessary toggling by deferring the notification disabling in canReadNotification() to the next notification cycle. Change-Id: Iebc5a7ad18a6f40ea1cf63e7f1b12f6c180cbf7a Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
This commit is contained in:
parent
115d4fc8cc
commit
ccb693299e
@ -563,6 +563,7 @@ QAbstractSocketPrivate::QAbstractSocketPrivate()
|
|||||||
cachedSocketDescriptor(-1),
|
cachedSocketDescriptor(-1),
|
||||||
readBufferMaxSize(0),
|
readBufferMaxSize(0),
|
||||||
isBuffered(false),
|
isBuffered(false),
|
||||||
|
hasPendingData(false),
|
||||||
connectTimer(0),
|
connectTimer(0),
|
||||||
disconnectTimer(0),
|
disconnectTimer(0),
|
||||||
hostLookupId(-1),
|
hostLookupId(-1),
|
||||||
@ -593,6 +594,7 @@ void QAbstractSocketPrivate::resetSocketLayer()
|
|||||||
qDebug("QAbstractSocketPrivate::resetSocketLayer()");
|
qDebug("QAbstractSocketPrivate::resetSocketLayer()");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
hasPendingData = false;
|
||||||
if (socketEngine) {
|
if (socketEngine) {
|
||||||
socketEngine->close();
|
socketEngine->close();
|
||||||
socketEngine->disconnect();
|
socketEngine->disconnect();
|
||||||
@ -683,8 +685,13 @@ bool QAbstractSocketPrivate::canReadNotification()
|
|||||||
qDebug("QAbstractSocketPrivate::canReadNotification()");
|
qDebug("QAbstractSocketPrivate::canReadNotification()");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!isBuffered)
|
if (!isBuffered) {
|
||||||
|
if (hasPendingData) {
|
||||||
socketEngine->setReadNotificationEnabled(false);
|
socketEngine->setReadNotificationEnabled(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
hasPendingData = true;
|
||||||
|
}
|
||||||
|
|
||||||
// If buffered, read data from the socket into the read buffer
|
// If buffered, read data from the socket into the read buffer
|
||||||
qint64 newBytes = 0;
|
qint64 newBytes = 0;
|
||||||
@ -2434,6 +2441,7 @@ qint64 QAbstractSocket::readData(char *data, qint64 maxSize)
|
|||||||
d->state = QAbstractSocket::UnconnectedState;
|
d->state = QAbstractSocket::UnconnectedState;
|
||||||
} else {
|
} else {
|
||||||
// Only do this when there was no error
|
// Only do this when there was no error
|
||||||
|
d->hasPendingData = false;
|
||||||
d->socketEngine->setReadNotificationEnabled(true);
|
d->socketEngine->setReadNotificationEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +143,7 @@ public:
|
|||||||
|
|
||||||
qint64 readBufferMaxSize;
|
qint64 readBufferMaxSize;
|
||||||
bool isBuffered;
|
bool isBuffered;
|
||||||
|
bool hasPendingData;
|
||||||
|
|
||||||
QTimer *connectTimer;
|
QTimer *connectTimer;
|
||||||
QTimer *disconnectTimer;
|
QTimer *disconnectTimer;
|
||||||
|
@ -398,7 +398,8 @@ qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *addres
|
|||||||
readBytes = d->socketEngine->readDatagram(data, maxSize);
|
readBytes = d->socketEngine->readDatagram(data, maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
d_func()->socketEngine->setReadNotificationEnabled(true);
|
d->hasPendingData = false;
|
||||||
|
d->socketEngine->setReadNotificationEnabled(true);
|
||||||
if (readBytes < 0)
|
if (readBytes < 0)
|
||||||
d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
|
d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
|
||||||
return readBytes;
|
return readBytes;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user