diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2014-04-15 18:50:53 +0400 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-05-15 13:53:14 +0200 |
commit | b749c9dc00f22ecfcf4be6684b3596b20f7ae0c4 (patch) | |
tree | 6abe71aaa86a26acdac4114cb601fb44299b8e14 | |
parent | 1fc75ea6056b8546e5aea136fe580f97e833b828 (diff) | |
download | qtserialport-b749c9dc00f22ecfcf4be6684b3596b20f7ae0c4.tar.gz |
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 <Sergey.Belyashov@gmail.com>
Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
-rw-r--r-- | src/serialport/qserialport_win.cpp | 39 | ||||
-rw-r--r-- | 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 <QtCore/qelapsedtimer.h> #include <QtCore/qvector.h> +#include <QtCore/qtimer.h> #endif #include <QtCore/qwineventnotifier.h> @@ -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 <QtCore/qhash.h> QT_BEGIN_NAMESPACE class QWinEventNotifier; +class QTimer; #else #include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE @@ -131,6 +132,7 @@ public: QWinEventNotifier *communicationNotifier; QWinEventNotifier *readCompletionNotifier; QWinEventNotifier *writeCompletionNotifier; + QTimer *startAsyncWriteTimer; OVERLAPPED communicationOverlapped; OVERLAPPED readCompletionOverlapped; OVERLAPPED writeCompletionOverlapped; |