QLocalSocket: reimplement readLineData() function

The base implementation reads data using repeated calls to getChar(),
which is quite slow.

Change-Id: Ie46624df63791b2cdd3c8a28fe3327427d942505
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
bb10
Alex Trotsenko 2021-06-23 18:26:10 +03:00
parent 46d2ba1ea4
commit b3fbfcd373
7 changed files with 76 additions and 9 deletions

View File

@ -208,6 +208,30 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
return readSoFar;
}
/*!
Reads a line from the internal buffer, but no more than \c{maxlen}
characters. A terminating '\0' byte is always appended to \c{data},
so \c{maxlen} must be larger than 1.
*/
qint64 QWindowsPipeReader::readLine(char *data, qint64 maxlen)
{
QMutexLocker locker(&mutex);
qint64 readSoFar = 0;
if (actualReadBufferSize > 0) {
readSoFar = readBuffer.readLine(data, qMin(actualReadBufferSize + 1, maxlen));
actualReadBufferSize -= readSoFar;
}
if (!pipeBroken) {
startAsyncReadHelper(&locker);
if (readSoFar == 0)
return -2; // signal EWOULDBLOCK
}
return readSoFar;
}
/*!
Returns \c true if a complete line of data can be read from the buffer.
*/

View File

@ -78,6 +78,7 @@ public:
bool isPipeClosed() const { return pipeBroken; }
qint64 bytesAvailable() const;
qint64 read(char *data, qint64 maxlen);
qint64 readLine(char *data, qint64 maxlen);
bool canReadLine() const;
DWORD checkPipeState();
bool checkForReadyRead() { return consumePendingAndEmit(false); }

View File

@ -166,6 +166,11 @@ QT_BEGIN_NAMESPACE
\reimp
*/
/*!
\fn qint64 QLocalSocket::readLineData(char *data, qint64 maxSize)
\reimp
*/
/*!
\fn qint64 QLocalSocket::skipData(qint64 maxSize)
\reimp

View File

@ -139,6 +139,7 @@ Q_SIGNALS:
protected:
virtual qint64 readData(char*, qint64) override;
qint64 readLineData(char *data, qint64 maxSize) override;
qint64 skipData(qint64 maxSize) override;
virtual qint64 writeData(const char*, qint64) override;

View File

@ -301,6 +301,16 @@ qint64 QLocalSocket::readData(char *data, qint64 c)
return d->tcpSocket->read(data, c);
}
qint64 QLocalSocket::readLineData(char *data, qint64 maxSize)
{
if (!maxSize)
return 0;
// QIODevice::readLine() reserves space for the trailing '\0' byte,
// so we must read 'maxSize + 1' bytes.
return d_func()->tcpSocket->readLine(data, maxSize + 1);
}
qint64 QLocalSocket::skipData(qint64 maxSize)
{
return d_func()->tcpSocket->skip(maxSize);

View File

@ -483,6 +483,16 @@ qint64 QLocalSocket::readData(char *data, qint64 c)
return d->unixSocket.read(data, c);
}
qint64 QLocalSocket::readLineData(char *data, qint64 maxSize)
{
if (!maxSize)
return 0;
// QIODevice::readLine() reserves space for the trailing '\0' byte,
// so we must read 'maxSize + 1' bytes.
return d_func()->unixSocket.readLine(data, maxSize + 1);
}
qint64 QLocalSocket::skipData(qint64 maxSize)
{
return d_func()->unixSocket.skip(maxSize);

View File

@ -238,6 +238,20 @@ void QLocalSocket::connectToServer(OpenMode openMode)
emit connected();
}
static qint64 tranformPipeReaderResult(qint64 res)
{
// QWindowsPipeReader's reading functions return error codes
// that don't match what we need.
switch (res) {
case 0: // EOF -> transform to error
return -1;
case -2: // EWOULDBLOCK -> no error, just no bytes
return 0;
default:
return res;
}
}
// This is reading from the buffer
qint64 QLocalSocket::readData(char *data, qint64 maxSize)
{
@ -246,17 +260,19 @@ qint64 QLocalSocket::readData(char *data, qint64 maxSize)
if (!maxSize)
return 0;
qint64 ret = d->pipeReader->read(data, maxSize);
return tranformPipeReaderResult(d->pipeReader->read(data, maxSize));
}
// QWindowsPipeReader::read() returns error codes that don't match what we need
switch (ret) {
case 0: // EOF -> transform to error
return -1;
case -2: // EWOULDBLOCK -> no error, just no bytes
qint64 QLocalSocket::readLineData(char *data, qint64 maxSize)
{
Q_D(QLocalSocket);
if (!maxSize)
return 0;
default:
return ret;
}
// QIODevice::readLine() reserves space for the trailing '\0' byte,
// so we must read 'maxSize + 1' bytes.
return tranformPipeReaderResult(d->pipeReader->readLine(data, maxSize + 1));
}
qint64 QLocalSocket::skipData(qint64 maxSize)