Mercurial > hg > piper-cpp
diff vamp-client/ProcessQtTransport.h @ 126:2004ec2b653e
Ensure we read right up to end of buffered data after server exits; adjust waiting schedule on Windows (where waitForReadyRead is far too wasteful of sleep time)
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Fri, 28 Oct 2016 14:31:58 +0100 |
parents | ea06fae1567c |
children | 3dcf0394971d |
line wrap: on
line diff
--- a/vamp-client/ProcessQtTransport.h Fri Oct 28 11:08:17 2016 +0100 +++ b/vamp-client/ProcessQtTransport.h Fri Oct 28 14:31:58 2016 +0100 @@ -64,7 +64,8 @@ { public: ProcessQtTransport(std::string processName, std::string formatArg) : - m_completenessChecker(0) { + m_completenessChecker(0), + m_crashed(false) { m_process = new QProcess(); m_process->setReadChannel(QProcess::StandardOutput); @@ -110,29 +111,31 @@ void setCompletenessChecker(MessageCompletenessChecker *checker) override { - //!!! ownership? m_completenessChecker = checker; } bool isOK() const override { - return m_process != nullptr; + return (m_process != nullptr) && !m_crashed; } std::vector<char> - call(const char *ptr, size_t size) override { + call(const char *ptr, size_t size, bool slow) override { QMutexLocker locker(&m_mutex); if (!m_completenessChecker) { throw std::logic_error("No completeness checker set on transport"); } + if (!isOK()) { + throw std::logic_error("Transport is not OK"); + } #ifdef DEBUG_TRANSPORT std::cerr << "writing " << size << " bytes to server" << std::endl; #endif m_process->write(ptr, size); - m_process->waitForBytesWritten(1000); + m_process->waitForBytesWritten(); std::vector<char> buffer; bool complete = false; @@ -145,9 +148,25 @@ #ifdef DEBUG_TRANSPORT std::cerr << "waiting for data from server..." << std::endl; #endif - m_process->waitForReadyRead(1000); - - if (m_process->state() == QProcess::NotRunning) { + if (slow) { + m_process->waitForReadyRead(1000); + } else { +#ifdef _WIN32 + // This is most unsatisfactory -- if we give a non-zero + // arg here, then we end up sleeping way beyond the arrival + // of the data to read -- can end up using less than 10% + // CPU during processing which is crazy. So for Windows + // only, we busy-wait during "fast" calls. It works out + // much faster in the end. Could do with a simpler native + // blocking API really. + m_process->waitForReadyRead(0); +#else + m_process->waitForReadyRead(100); +#endif + } + if (m_process->state() == QProcess::NotRunning && + // don't give up until we've read all that's been buffered! + !m_process->bytesAvailable()) { QProcess::ProcessError err = m_process->error(); if (err == QProcess::Crashed) { std::cerr << "Server crashed during request" << std::endl; @@ -155,6 +174,7 @@ std::cerr << "Server failed during request with error code " << err << std::endl; } + m_crashed = true; throw ServerCrashed(); } } else { @@ -172,6 +192,7 @@ MessageCompletenessChecker *m_completenessChecker; //!!! I don't own this (currently) QProcess *m_process; // I own this QMutex m_mutex; + bool m_crashed; }; }