diff --git a/article_netmgr.cc b/article_netmgr.cc index 21535796..aeefb5d1 100644 --- a/article_netmgr.cc +++ b/article_netmgr.cc @@ -442,6 +442,14 @@ qint64 ArticleResourceReply::bytesAvailable() const return avail - alreadyRead + QNetworkReply::bytesAvailable(); } +bool ArticleResourceReply::atEnd() const +{ + // QWebEngineUrlRequestJob finishes and is destroyed as soon as QIODevice::atEnd() returns true. + // QNetworkReply::atEnd() returns true while bytesAvailable() returns 0. + // Return false if the data request is not finished to work around always-blank web page. + return req->isFinished() && QNetworkReply::atEnd(); +} + qint64 ArticleResourceReply::readData( char * out, qint64 maxSize ) { // From the doc: "This function might be called with a maxSize of 0, @@ -458,6 +466,18 @@ qint64 ArticleResourceReply::readData( char * out, qint64 maxSize ) qint64 left = avail - alreadyRead; + if( left == 0 && !finished ) + { + // Work around endlessly repeated useless calls to readData(). The sleep duration is a tradeoff. + // On the one hand, lowering the duration reduces CPU usage. On the other hand, overly long + // sleep duration reduces page content update frequency in the web view. + // Waiting on a condition variable is more complex and actually works worse than + // simple fixed-duration sleeping, because the web view is not updated until + // the data request is finished if readData() returns only when new data arrives. + QThread::msleep( 30 ); + return 0; + } + qint64 toRead = maxSize < left ? maxSize : left; GD_DPRINTF( "====reading %d of (%d) bytes . Finished: %d", (int)toRead, avail, finished ); diff --git a/article_netmgr.hh b/article_netmgr.hh index a0dcdeb8..3af7f848 100644 --- a/article_netmgr.hh +++ b/article_netmgr.hh @@ -148,7 +148,7 @@ public: protected: virtual qint64 bytesAvailable() const; - + bool atEnd() const override; virtual void abort() {} virtual qint64 readData( char * data, qint64 maxSize ); diff --git a/dictionary.cc b/dictionary.cc index 63e8514b..3a606dd6 100644 --- a/dictionary.cc +++ b/dictionary.cc @@ -117,7 +117,6 @@ void DataRequest::appendDataSlice( const void * buffer, size_t size ) { data.resize( data.size() + size ); memcpy( &data.front() + offset, buffer, size ); - cond.wakeAll(); } void DataRequest::getDataSlice( size_t offset, size_t size, void * buffer ) @@ -130,22 +129,9 @@ void DataRequest::getDataSlice( size_t offset, size_t size, void * buffer ) if( !hasAnyData ) throw exSliceOutOfRange(); - while( offset + size > data.size() && !quit ) { - cond.wait( &dataMutex,10 ); - } - if(quit) - return; - memcpy( buffer, &data[ offset ], size ); } -DataRequest::~DataRequest() -{ - quit = true; - cond.wakeAll(); - finish(); -} - vector< char > & DataRequest::getFullData() { if ( !isFinished() ) diff --git a/dictionary.hh b/dictionary.hh index cdb0c5f0..740e4490 100644 --- a/dictionary.hh +++ b/dictionary.hh @@ -201,18 +201,13 @@ public: { } - ~DataRequest(); - protected: // Subclasses should be filling up the 'data' array, locking the mutex when // whey work with it. Mutex dataMutex; - QWaitCondition cond; - bool hasAnyData; // With this being false, dataSize() always returns -1 - bool quit = false; vector< char > data; };