summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2014-04-15 18:50:53 +0400
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-05-15 13:53:14 +0200
commitb749c9dc00f22ecfcf4be6684b3596b20f7ae0c4 (patch)
tree6abe71aaa86a26acdac4114cb601fb44299b8e14
parent1fc75ea6056b8546e5aea136fe580f97e833b828 (diff)
downloadqtserialport-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.cpp39
-rw-r--r--src/serialport/qserialport_win_p.h2
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;