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:
Alex Trotsenko 2016-04-01 13:19:10 +03:00
parent 115d4fc8cc
commit ccb693299e
3 changed files with 13 additions and 3 deletions

View File

@ -563,6 +563,7 @@ QAbstractSocketPrivate::QAbstractSocketPrivate()
cachedSocketDescriptor(-1),
readBufferMaxSize(0),
isBuffered(false),
hasPendingData(false),
connectTimer(0),
disconnectTimer(0),
hostLookupId(-1),
@ -593,6 +594,7 @@ void QAbstractSocketPrivate::resetSocketLayer()
qDebug("QAbstractSocketPrivate::resetSocketLayer()");
#endif
hasPendingData = false;
if (socketEngine) {
socketEngine->close();
socketEngine->disconnect();
@ -683,8 +685,13 @@ bool QAbstractSocketPrivate::canReadNotification()
qDebug("QAbstractSocketPrivate::canReadNotification()");
#endif
if (!isBuffered)
socketEngine->setReadNotificationEnabled(false);
if (!isBuffered) {
if (hasPendingData) {
socketEngine->setReadNotificationEnabled(false);
return true;
}
hasPendingData = true;
}
// If buffered, read data from the socket into the read buffer
qint64 newBytes = 0;
@ -2434,6 +2441,7 @@ qint64 QAbstractSocket::readData(char *data, qint64 maxSize)
d->state = QAbstractSocket::UnconnectedState;
} else {
// Only do this when there was no error
d->hasPendingData = false;
d->socketEngine->setReadNotificationEnabled(true);
}

View File

@ -143,6 +143,7 @@ public:
qint64 readBufferMaxSize;
bool isBuffered;
bool hasPendingData;
QTimer *connectTimer;
QTimer *disconnectTimer;

View File

@ -398,7 +398,8 @@ qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *addres
readBytes = d->socketEngine->readDatagram(data, maxSize);
}
d_func()->socketEngine->setReadNotificationEnabled(true);
d->hasPendingData = false;
d->socketEngine->setReadNotificationEnabled(true);
if (readBytes < 0)
d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
return readBytes;