summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarkus Goetz <markus@woboq.com>2014-07-23 16:35:01 +0200
committerMarkus Goetz <markus@woboq.com>2014-07-25 12:56:14 +0200
commitb99fa32d70e6511ae8bc1c6e806dbbb042dc8090 (patch)
tree6e1a3a98253eb1eabb6419a277b5419df4ad0611 /src
parent3a9763d3492ef9c26a63c86e8a024fab3ce5807a (diff)
QNAM: Fix CPU load for limited upload QIODevice
This fixes high CPU load for upload devices that don't generate a constant stream of data. Their readData() function was called all the time without returning actual data. This was noticed when implementing an upload device that emits data in a limited way for bandwidth limiting. [ChangeLog][QtNetwork][QNetworkAccessManager] Fixed high CPU load when handling POST/upload QIODevice that generates data on readyRead(). Change-Id: Iefbcb1a21d8aedef1eb11761232dd16a049018dc Reviewed-by: Richard J. Moore <rich@kde.org>
Diffstat (limited to 'src')
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp19
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h4
2 files changed, 23 insertions, 0 deletions
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 56105a544b..4efb2f6a2a 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -863,6 +863,11 @@ void QNetworkReplyHttpImplPrivate::postRequest()
forwardUploadDevice->setParent(delegate); // needed to make sure it is moved on moveToThread()
delegate->httpRequest.setUploadByteDevice(forwardUploadDevice);
+ // If the device in the user thread claims it has more data, keep the flow to HTTP thread going
+ QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()),
+ q, SLOT(uploadByteDeviceReadyReadSlot()),
+ Qt::QueuedConnection);
+
// From main thread to user thread:
QObject::connect(q, SIGNAL(haveUploadData(QByteArray,bool,qint64)),
forwardUploadDevice, SLOT(haveDataSlot(QByteArray,bool,qint64)), Qt::QueuedConnection);
@@ -1284,6 +1289,13 @@ void QNetworkReplyHttpImplPrivate::wantUploadDataSlot(qint64 maxSize)
// call readPointer
qint64 currentUploadDataLength = 0;
char *data = const_cast<char*>(uploadByteDevice->readPointer(maxSize, currentUploadDataLength));
+
+ if (currentUploadDataLength == 0) {
+ // No bytes from upload byte device. There will be bytes later, it will emit readyRead()
+ // and our uploadByteDeviceReadyReadSlot() is called.
+ return;
+ }
+
// Let's make a copy of this data
QByteArray dataArray(data, currentUploadDataLength);
@@ -1291,6 +1303,13 @@ void QNetworkReplyHttpImplPrivate::wantUploadDataSlot(qint64 maxSize)
emit q->haveUploadData(dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size());
}
+void QNetworkReplyHttpImplPrivate::uploadByteDeviceReadyReadSlot()
+{
+ // Start the flow between this thread and the HTTP thread again by triggering a upload.
+ wantUploadDataSlot(1024);
+}
+
+
/*
A simple web page that can be used to test us: http://www.procata.com/cachetest/
*/
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index d21659ce82..06a5383ae4 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -129,6 +129,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void resetUploadDataSlot(bool *r))
Q_PRIVATE_SLOT(d_func(), void wantUploadDataSlot(qint64))
Q_PRIVATE_SLOT(d_func(), void sentUploadDataSlot(qint64))
+ Q_PRIVATE_SLOT(d_func(), void uploadByteDeviceReadyReadSlot())
Q_PRIVATE_SLOT(d_func(), void emitReplyUploadProgress(qint64, qint64))
Q_PRIVATE_SLOT(d_func(), void _q_cacheSaveDeviceAboutToClose())
@@ -300,6 +301,9 @@ public:
void wantUploadDataSlot(qint64);
void sentUploadDataSlot(qint64);
+ // From user's QNonContiguousByteDevice
+ void uploadByteDeviceReadyReadSlot();
+
Q_DECLARE_PUBLIC(QNetworkReplyHttpImpl)
};