From b749c9dc00f22ecfcf4be6684b3596b20f7ae0c4 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Tue, 15 Apr 2014 18:50:53 +0400 Subject: Use QTimer to defer starting of writing on Windows The Win32 API has not possibility to do same behavior as on *nix to defer a write operation to next event-loop. In *nix implementation enabling of the write SocketNotifier guarantees that write operation will begin on the following cycle of event-loop in case the TxFIFO of the driver is empty. It give an feature of deferred data transfer where is possible to use chain of the QSerialPort::write() methods which just accumulate data in writeBuffer. Also it gives the chance to simple implement of the waitForBytesWrite() method. But in Windows implementation the first call of the QSerialPort::write() leads to startup of data transfer. And the subsequent calls of this method simply accumulate data while the previous operation won't completed. It leads to a payload data are transferred by chunks and to increase of loading of the write notifier. Also it complicates implementation of the waitForBytesWritten() method which works not in compliance with documentation. The decision is use of additional QTimer with a zero interval which launches data transfer on the following event-loop cycle. Tested on Windows 8 using the virtual com0com serial ports and set of the cwriter(a)sync examples with use Qt5. Change-Id: Iaea404198e440f6cb191f168561c977d18e9f4ca Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialport_win.cpp | 39 ++++++++++++++++++++++++++------------ src/serialport/qserialport_win_p.h | 2 ++ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 9b04083..6e6f7c6 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -48,6 +48,7 @@ #ifndef Q_OS_WINCE #include #include +#include #endif #include @@ -106,6 +107,7 @@ QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q) , communicationNotifier(new QWinEventNotifier(q)) , readCompletionNotifier(new QWinEventNotifier(q)) , writeCompletionNotifier(new QWinEventNotifier(q)) + , startAsyncWriteTimer(0) , originalEventMask(0) , triggeredEventMask(0) { @@ -378,8 +380,16 @@ bool QSerialPortPrivate::setBreakEnabled(bool set) void QSerialPortPrivate::startWriting() { - if (!writeStarted) - startAsyncWrite(); + Q_Q(QSerialPort); + + if (!writeStarted) { + if (!startAsyncWriteTimer) { + startAsyncWriteTimer = new QTimer(q); + q->connect(startAsyncWriteTimer, SIGNAL(timeout()), q, SLOT(_q_completeAsyncWrite())); + startAsyncWriteTimer->setSingleShot(true); + } + startAsyncWriteTimer->start(0); + } } bool QSerialPortPrivate::waitForReadyRead(int msecs) @@ -432,6 +442,9 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs) QElapsedTimer stopWatch; stopWatch.start(); + if (!writeStarted) + startAsyncWrite(); + forever { bool timedOut = false; HANDLE triggeredEvent = 0; @@ -620,17 +633,19 @@ void QSerialPortPrivate::_q_completeAsyncWrite() { Q_Q(QSerialPort); - writeStarted = false; - DWORD numberOfBytesTransferred = 0; - if (!::GetOverlappedResult(handle, &writeCompletionOverlapped, &numberOfBytesTransferred, FALSE)) { - numberOfBytesTransferred = 0; - q->setError(decodeSystemError()); - return; - } + if (writeStarted) { + writeStarted = false; + DWORD numberOfBytesTransferred = 0; + if (!::GetOverlappedResult(handle, &writeCompletionOverlapped, &numberOfBytesTransferred, FALSE)) { + numberOfBytesTransferred = 0; + q->setError(decodeSystemError()); + return; + } - if (numberOfBytesTransferred > 0) { - writeBuffer.free(numberOfBytesTransferred); - emit q->bytesWritten(numberOfBytesTransferred); + if (numberOfBytesTransferred > 0) { + writeBuffer.free(numberOfBytesTransferred); + emit q->bytesWritten(numberOfBytesTransferred); + } } startAsyncWrite(); diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h index dd6ae0e..461226b 100644 --- a/src/serialport/qserialport_win_p.h +++ b/src/serialport/qserialport_win_p.h @@ -51,6 +51,7 @@ #include QT_BEGIN_NAMESPACE class QWinEventNotifier; +class QTimer; #else #include QT_BEGIN_NAMESPACE @@ -131,6 +132,7 @@ public: QWinEventNotifier *communicationNotifier; QWinEventNotifier *readCompletionNotifier; QWinEventNotifier *writeCompletionNotifier; + QTimer *startAsyncWriteTimer; OVERLAPPED communicationOverlapped; OVERLAPPED readCompletionOverlapped; OVERLAPPED writeCompletionOverlapped; -- cgit v1.2.1