summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@nokia.com>2012-01-16 12:26:40 +0100
committerQt by Nokia <qt-info@nokia.com>2012-01-24 14:40:32 +0100
commit3bc42e860d039147de0c22c0db0ad756ccc060de (patch)
treec729a9aa48fb29edb85c91ba66c353a71db915f2 /src
parent096b49bc1e66af2e6347bafc435b361a15639872 (diff)
use QWinOverlappedIoNotifier in QWindowsPipeReader
Change-Id: I71d5feaa07e8febd6c562be1dc6d7790e3a1606c Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qwindowspipereader.cpp162
-rw-r--r--src/corelib/io/qwindowspipereader_p.h12
2 files changed, 83 insertions, 91 deletions
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 2938a7501b..7979ee77df 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -40,11 +40,11 @@
****************************************************************************/
#include "qwindowspipereader_p.h"
+#include "qwinoverlappedionotifier_p.h"
#include <qdebug.h>
#include <qelapsedtimer.h>
#include <qeventloop.h>
#include <qtimer.h>
-#include <qwineventnotifier.h>
QT_BEGIN_NAMESPACE
@@ -53,21 +53,23 @@ QWindowsPipeReader::QWindowsPipeReader(QObject *parent)
handle(INVALID_HANDLE_VALUE),
readBufferMaxSize(0),
actualReadBufferSize(0),
+ readSequenceStarted(false),
emitReadyReadTimer(new QTimer(this)),
- pipeBroken(false)
+ pipeBroken(false),
+ readyReadEmitted(false)
{
emitReadyReadTimer->setSingleShot(true);
connect(emitReadyReadTimer, SIGNAL(timeout()), SIGNAL(readyRead()));
-
- ZeroMemory(&overlapped, sizeof(overlapped));
- overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- dataReadNotifier = new QWinEventNotifier(overlapped.hEvent, this);
- connect(dataReadNotifier, SIGNAL(activated(HANDLE)), SLOT(readEventSignalled()));
+ dataReadNotifier = new QWinOverlappedIoNotifier(this);
+ connect(dataReadNotifier, &QWinOverlappedIoNotifier::notified, this, &QWindowsPipeReader::notified);
}
QWindowsPipeReader::~QWindowsPipeReader()
{
- CloseHandle(overlapped.hEvent);
+ if (readSequenceStarted) {
+ CancelIoEx(handle, &overlapped);
+ dataReadNotifier->waitForNotified(-1);
+ }
}
/*!
@@ -78,8 +80,13 @@ void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
readBuffer.clear();
actualReadBufferSize = 0;
handle = hPipeReadEnd;
+ ZeroMemory(&overlapped, sizeof(overlapped));
pipeBroken = false;
- dataReadNotifier->setEnabled(true);
+ readyReadEmitted = false;
+ if (hPipeReadEnd != INVALID_HANDLE_VALUE) {
+ dataReadNotifier->setHandle(hPipeReadEnd);
+ dataReadNotifier->setEnabled(true);
+ }
}
/*!
@@ -92,7 +99,6 @@ void QWindowsPipeReader::stop()
dataReadNotifier->setEnabled(false);
readSequenceStarted = false;
handle = INVALID_HANDLE_VALUE;
- ResetEvent(overlapped.hEvent);
}
/*!
@@ -149,19 +155,18 @@ bool QWindowsPipeReader::canReadLine() const
/*!
\internal
Will be called whenever the read operation completes.
- Returns true, if readyRead() has been emitted.
*/
-bool QWindowsPipeReader::readEventSignalled()
+void QWindowsPipeReader::notified(DWORD numberOfBytesRead, DWORD errorCode)
{
- if (!completeAsyncRead()) {
+ if (!completeAsyncRead(numberOfBytesRead, errorCode)) {
pipeBroken = true;
emit pipeClosed();
- return false;
+ return;
}
startAsyncRead();
emitReadyReadTimer->stop();
+ readyReadEmitted = true;
emit readyRead();
- return true;
}
/*!
@@ -170,56 +175,49 @@ bool QWindowsPipeReader::readEventSignalled()
*/
void QWindowsPipeReader::startAsyncRead()
{
- do {
- DWORD bytesToRead = checkPipeState();
- if (pipeBroken)
- return;
+ DWORD bytesToRead = qMax(checkPipeState(), minReadBufferSize);
+ if (pipeBroken)
+ return;
+ if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) {
+ bytesToRead = readBufferMaxSize - readBuffer.size();
if (bytesToRead == 0) {
- // There are no bytes in the pipe but we need to
- // start the overlapped read with some buffer size.
- bytesToRead = initialReadBufferSize;
- }
-
- if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) {
- bytesToRead = readBufferMaxSize - readBuffer.size();
- if (bytesToRead == 0) {
- // Buffer is full. User must read data from the buffer
- // before we can read more from the pipe.
- return;
- }
+ // Buffer is full. User must read data from the buffer
+ // before we can read more from the pipe.
+ return;
}
+ }
- char *ptr = readBuffer.reserve(bytesToRead);
+ char *ptr = readBuffer.reserve(bytesToRead);
- readSequenceStarted = true;
- if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
- completeAsyncRead();
- } else {
- switch (GetLastError()) {
- case ERROR_IO_PENDING:
- // This is not an error. We're getting notified, when data arrives.
- return;
- case ERROR_MORE_DATA:
- // This is not an error. The synchronous read succeeded.
- // We're connected to a message mode pipe and the message
- // didn't fit into the pipe's system buffer.
- completeAsyncRead();
- break;
- case ERROR_PIPE_NOT_CONNECTED:
- {
- // It may happen, that the other side closes the connection directly
- // after writing data. Then we must set the appropriate socket state.
- pipeBroken = true;
- emit pipeClosed();
- return;
- }
- default:
- emit winError(GetLastError(), QLatin1String("QWindowsPipeReader::startAsyncRead"));
- return;
+ readSequenceStarted = true;
+ if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
+ // We get notified by the QWinOverlappedIoNotifier - even in the synchronous case.
+ return;
+ } else {
+ switch (GetLastError()) {
+ case ERROR_IO_PENDING:
+ // This is not an error. We're getting notified, when data arrives.
+ return;
+ case ERROR_MORE_DATA:
+ // This is not an error. The synchronous read succeeded.
+ // We're connected to a message mode pipe and the message
+ // didn't fit into the pipe's system buffer.
+ // We're getting notified by the QWinOverlappedIoNotifier.
+ break;
+ case ERROR_PIPE_NOT_CONNECTED:
+ {
+ // It may happen, that the other side closes the connection directly
+ // after writing data. Then we must set the appropriate socket state.
+ pipeBroken = true;
+ emit pipeClosed();
+ return;
}
+ default:
+ emit winError(GetLastError(), QLatin1String("QWindowsPipeReader::startAsyncRead"));
+ return;
}
- } while (!readSequenceStarted);
+ }
}
/*!
@@ -227,26 +225,24 @@ void QWindowsPipeReader::startAsyncRead()
Sets the correct size of the read buffer after a read operation.
Returns false, if an error occurred or the connection dropped.
*/
-bool QWindowsPipeReader::completeAsyncRead()
+bool QWindowsPipeReader::completeAsyncRead(DWORD bytesRead, DWORD errorCode)
{
- ResetEvent(overlapped.hEvent);
readSequenceStarted = false;
- DWORD bytesRead;
- if (!GetOverlappedResult(handle, &overlapped, &bytesRead, TRUE)) {
- switch (GetLastError()) {
- case ERROR_MORE_DATA:
- // This is not an error. We're connected to a message mode
- // pipe and the message didn't fit into the pipe's system
- // buffer. We will read the remaining data in the next call.
- break;
- case ERROR_BROKEN_PIPE:
- case ERROR_PIPE_NOT_CONNECTED:
- return false;
- default:
- emit winError(GetLastError(), QLatin1String("QWindowsPipeReader::completeAsyncRead"));
- return false;
- }
+ switch (errorCode) {
+ case ERROR_SUCCESS:
+ break;
+ case ERROR_MORE_DATA:
+ // This is not an error. We're connected to a message mode
+ // pipe and the message didn't fit into the pipe's system
+ // buffer. We will read the remaining data in the next call.
+ break;
+ case ERROR_BROKEN_PIPE:
+ case ERROR_PIPE_NOT_CONNECTED:
+ return false;
+ default:
+ emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead"));
+ return false;
}
actualReadBufferSize += bytesRead;
@@ -281,17 +277,11 @@ DWORD QWindowsPipeReader::checkPipeState()
*/
bool QWindowsPipeReader::waitForReadyRead(int msecs)
{
- Q_ASSERT(readSequenceStarted);
- DWORD result = WaitForSingleObject(overlapped.hEvent, msecs == -1 ? INFINITE : msecs);
- switch (result) {
- case WAIT_OBJECT_0:
- return readEventSignalled();
- case WAIT_TIMEOUT:
- return false;
- }
-
- qWarning("QWindowsPipeReader::waitForReadyRead WaitForSingleObject failed with error code %d.", int(GetLastError()));
- return false;
+ if (!readSequenceStarted)
+ return false;
+ readyReadEmitted = false;
+ dataReadNotifier->waitForNotified(msecs);
+ return readyReadEmitted;
}
/*!
diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h
index 132c3540c0..2d979c337b 100644
--- a/src/corelib/io/qwindowspipereader_p.h
+++ b/src/corelib/io/qwindowspipereader_p.h
@@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Core)
-class QWinEventNotifier;
+class QWinOverlappedIoNotifier;
class Q_CORE_EXPORT QWindowsPipeReader : public QObject
{
@@ -89,7 +89,7 @@ public:
bool waitForPipeClosed(int msecs);
void startAsyncRead();
- bool completeAsyncRead();
+ bool isReadOperationActive() const { return readSequenceStarted; }
Q_SIGNALS:
void winError(ulong, const QString &);
@@ -97,22 +97,24 @@ Q_SIGNALS:
void pipeClosed();
private Q_SLOTS:
- bool readEventSignalled();
+ void notified(DWORD numberOfBytesRead, DWORD errorCode);
private:
+ bool completeAsyncRead(DWORD bytesRead, DWORD errorCode);
DWORD checkPipeState();
private:
HANDLE handle;
OVERLAPPED overlapped;
- QWinEventNotifier *dataReadNotifier;
+ QWinOverlappedIoNotifier *dataReadNotifier;
qint64 readBufferMaxSize;
QRingBuffer readBuffer;
int actualReadBufferSize;
bool readSequenceStarted;
QTimer *emitReadyReadTimer;
bool pipeBroken;
- static const qint64 initialReadBufferSize = 4096;
+ bool readyReadEmitted;
+ static const DWORD minReadBufferSize = 4096;
};
QT_END_NAMESPACE