summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2013-11-18 19:45:16 +0400
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-12-18 19:57:52 +0100
commit4e15aa6d7c4f9a03f4ae57b3ba04ade3400cccf1 (patch)
tree3d64db9afdb46c9e5ee54a3ff8ca98bdd7127ab8
parentd9725b249de5a2a6bb45e4f4e1a1b316d91ed102 (diff)
downloadqtserialport-4e15aa6d7c4f9a03f4ae57b3ba04ade3400cccf1.tar.gz
Use the signals/slots for internal events handling on Windows
The principal idea of this patch - to simplify a code and to minimize risks of UB in operation with the notifiers. Details are below: 1) Use a separate instances for the each notifier. It allows to get rid from an lookupXX() methods because now we always know which of notifiers was triggered. 2) Now each notifier is created once and used during serial port life. Moreover now in the open() and the close() methods are carried out a simply enabling and disabling of the notifiers. It allows to simplify code and to reduce overhead costs of check of a validity of the notifier pointers. 3) Use the signals/slots mechanism for the internal events handling. Use a slots excludes any UB in the notifier handlers because now isn't present a deep callbacks and so on. Even if some notifier will be deleted, we never got a crash at processing of triggered handle, we can just got an some error code and handle it. 4) There is no more need for existence of separate classes of notifiers which were inherited from the QWinEventNotifier. Now, the objects of QWinEventNotifier are use directly, only for delivery a triggered events to the appropriate slots. All logic of a events handling are in the _q_xx() slots. 5) The overlappedPointer() methods aren't necessary to us anymore. Now we know each OVERLAPPAD structure instance. It gives us to pass a pointers of these structures directly to the ReadFile/WriteFile/WaitCommEvent functions and have direct access to the hEvent field for the waitForXXX() methods. 6) The errors handling inside of the _q_xx() handlers are simplified. Now is not used a dptr-pointer to the QSerialPortPrivate class. So, earlier entered additional method QSerialPortPrivate::setError() is removed. This patch with using of slots is a strategic step because in the future in case of fix of a bug QTBUG-34946 instead of the QWinEventNotifier it is necessary to use the QWinOverlappedIoNotifier which provides only the signal/slot API. Note: Also this patch implicitly fix a bug QTBUG-33938. Task-number: QTBUG-33938 Change-Id: Iba9137e13e0bd6001c665434698b8cd965bc36e5 Reviewed-by: Sergey Belyashov <Sergey.Belyashov@gmail.com> Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
-rw-r--r--src/serialport/qserialport.h6
-rw-r--r--src/serialport/qserialport_win.cpp395
-rw-r--r--src/serialport/qserialport_win_p.h24
3 files changed, 174 insertions, 251 deletions
diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h
index 6e16463..c07af91 100644
--- a/src/serialport/qserialport.h
+++ b/src/serialport/qserialport.h
@@ -274,6 +274,12 @@ private:
QSerialPortPrivate * const d_ptr;
Q_DISABLE_COPY(QSerialPort)
+
+#if defined (Q_OS_WIN32) || defined(Q_OS_WIN64)
+ Q_PRIVATE_SLOT(d_func(), void _q_canCompleteCommunication())
+ Q_PRIVATE_SLOT(d_func(), void _q_canCompleteRead())
+ Q_PRIVATE_SLOT(d_func(), void _q_canCompleteWrite())
+#endif
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QSerialPort::Directions)
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 611f8bf..506dc94 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -96,157 +96,6 @@ static void initializeOverlappedStructure(OVERLAPPED &overlapped)
overlapped.OffsetHigh = 0;
}
-class AbstractOverlappedEventNotifier : public QWinEventNotifier
-{
- Q_OBJECT
-public:
- enum Type { CommEvent, ReadCompletionEvent, WriteCompletionEvent };
-
- AbstractOverlappedEventNotifier(QSerialPortPrivate *d, Type type, bool manual, QObject *parent)
- : QWinEventNotifier(parent), dptr(d), t(type) {
- ::ZeroMemory(&o, sizeof(o));
- o.hEvent = ::CreateEvent(NULL, manual, FALSE, NULL);
- if (!o.hEvent) {
- dptr->setError(dptr->decodeSystemError());
- } else {
- setHandle(o.hEvent);
- dptr->notifiers[o.hEvent] = this;
- }
- }
-
- virtual bool processCompletionRoutine() = 0;
-
- virtual ~AbstractOverlappedEventNotifier() {
- setEnabled(false);
- if (!::CloseHandle(o.hEvent))
- dptr->setError(dptr->decodeSystemError());
- }
-
- Type type() const { return t; }
- OVERLAPPED *overlappedPointer() { return &o; }
-
-protected:
- bool event(QEvent *e) Q_DECL_OVERRIDE {
- const bool ret = QWinEventNotifier::event(e);
- if (e->type() == QEvent::WinEventAct)
- processCompletionRoutine();
- return ret;
- }
-
- QSerialPortPrivate *dptr;
- Type t;
- OVERLAPPED o;
-};
-
-class CommOverlappedEventNotifier : public AbstractOverlappedEventNotifier
-{
- Q_OBJECT
-public:
- CommOverlappedEventNotifier(QSerialPortPrivate *d, DWORD eventMask, QObject *parent)
- : AbstractOverlappedEventNotifier(d, CommEvent, false, parent)
- , originalEventMask(eventMask), triggeredEventMask(0) {
- if (!::SetCommMask(dptr->descriptor, originalEventMask))
- dptr->setError(dptr->decodeSystemError());
- else
- startWaitCommEvent();
- }
-
- void startWaitCommEvent() {
- initializeOverlappedStructure(o);
- if (!::WaitCommEvent(dptr->descriptor, &triggeredEventMask, &o)) {
- const QSerialPort::SerialPortError error = dptr->decodeSystemError();
- if (error != QSerialPort::NoError) {
- dptr->setError(dptr->decodeSystemError());
- return;
- }
- }
- }
-
- bool processCompletionRoutine() Q_DECL_OVERRIDE {
- DWORD numberOfBytesTransferred = 0;
-
- if (!::GetOverlappedResult(dptr->descriptor, &o, &numberOfBytesTransferred, FALSE))
- dptr->setError(dptr->decodeSystemError());
-
- bool error = false;
-
- // Check for unexpected event. This event triggered when pulled previously
- // opened device from the system, when opened as for not to read and not to
- // write options and so forth.
- if (triggeredEventMask == 0)
- error = true;
-
- // Workaround for standard CDC ACM serial ports, for which triggered an
- // unexpected event EV_TXEMPTY at data transmission.
- if ((originalEventMask & triggeredEventMask) == 0) {
- if ((triggeredEventMask & EV_TXEMPTY) == 0)
- error = true;
- }
-
- // Start processing a caught error.
- if (error || (EV_ERR & triggeredEventMask))
- dptr->processIoErrors(error);
-
- if (!error)
- dptr->startAsyncRead();
-
- return !error;
- }
-
-private:
- DWORD originalEventMask;
- DWORD triggeredEventMask;
-};
-
-class ReadOverlappedCompletionNotifier : public AbstractOverlappedEventNotifier
-{
- Q_OBJECT
-public:
- ReadOverlappedCompletionNotifier(QSerialPortPrivate *d, QObject *parent)
- : AbstractOverlappedEventNotifier(d, ReadCompletionEvent, false, parent) {}
-
- bool processCompletionRoutine() Q_DECL_OVERRIDE {
- DWORD numberOfBytesTransferred = 0;
- if (!::GetOverlappedResult(dptr->descriptor, &o, &numberOfBytesTransferred, FALSE))
- dptr->setError(dptr->decodeSystemError());
-
- dptr->completeAsyncRead(numberOfBytesTransferred);
-
- // start async read for possible remainder into driver queue
- if ((numberOfBytesTransferred > 0) && (dptr->policy == QSerialPort::IgnorePolicy)) {
- dptr->startAsyncRead();
- } else { // driver queue is emplty, so startup wait comm event
- CommOverlappedEventNotifier *n =
- qobject_cast<CommOverlappedEventNotifier *>(dptr->lookupCommEventNotifier());
- if (n)
- n->startWaitCommEvent();
- }
-
- return true;
- }
-};
-
-class WriteOverlappedCompletionNotifier : public AbstractOverlappedEventNotifier
-{
- Q_OBJECT
-public:
- WriteOverlappedCompletionNotifier(QSerialPortPrivate *d, QObject *parent)
- : AbstractOverlappedEventNotifier(d, WriteCompletionEvent, false, parent) {}
-
- bool processCompletionRoutine() Q_DECL_OVERRIDE {
- DWORD numberOfBytesTransferred = 0;
- if (!::GetOverlappedResult(dptr->descriptor, &o, &numberOfBytesTransferred, FALSE)) {
- numberOfBytesTransferred = 0;
- dptr->setError(dptr->decodeSystemError());
- }
-
- dptr->completeAsyncWrite(numberOfBytesTransferred);
- return true;
- }
-};
-
-#include "qserialport_win.moc"
-
QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
: QSerialPortPrivateData(q)
, descriptor(INVALID_HANDLE_VALUE)
@@ -256,7 +105,38 @@ QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
, acyncWritePosition(0)
, readyReadEmitted(0)
, writeSequenceStarted(false)
+ , communicationNotifier(new QWinEventNotifier(q))
+ , readCompletionNotifier(new QWinEventNotifier(q))
+ , writeCompletionNotifier(new QWinEventNotifier(q))
+ , originalEventMask(0)
+ , triggeredEventMask(0)
{
+ ::ZeroMemory(&communicationOverlapped, sizeof(communicationOverlapped));
+ communicationOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!communicationOverlapped.hEvent)
+ q->setError(decodeSystemError());
+ else {
+ communicationNotifier->setHandle(communicationOverlapped.hEvent);
+ q->connect(communicationNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_canCompleteCommunication()));
+ }
+
+ ::ZeroMemory(&readCompletionOverlapped, sizeof(readCompletionOverlapped));
+ readCompletionOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!readCompletionOverlapped.hEvent)
+ q->setError(decodeSystemError());
+ else {
+ readCompletionNotifier->setHandle(readCompletionOverlapped.hEvent);
+ q->connect(readCompletionNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_canCompleteRead()));
+ }
+
+ ::ZeroMemory(&writeCompletionOverlapped, sizeof(writeCompletionOverlapped));
+ writeCompletionOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!writeCompletionOverlapped.hEvent)
+ q->setError(decodeSystemError());
+ else {
+ writeCompletionNotifier->setHandle(writeCompletionOverlapped.hEvent);
+ q->connect(writeCompletionNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_canCompleteWrite()));
+ }
}
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
@@ -264,7 +144,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
Q_Q(QSerialPort);
DWORD desiredAccess = 0;
- DWORD originalEventMask = EV_ERR;
+ originalEventMask = EV_ERR;
if (mode & QIODevice::ReadOnly) {
desiredAccess |= GENERIC_READ;
@@ -308,18 +188,27 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
if (!updateCommTimeouts())
return false;
- if (mode & QIODevice::ReadOnly) {
- QWinEventNotifier *n = new ReadOverlappedCompletionNotifier(this, q);
- n->setEnabled(true);
+ if (mode & QIODevice::ReadOnly)
+ readCompletionNotifier->setEnabled(true);
+
+ if (mode & QIODevice::WriteOnly)
+ writeCompletionNotifier->setEnabled(true);
+
+ if (!::SetCommMask(descriptor, originalEventMask)) {
+ q->setError(decodeSystemError());
+ return false;
}
- if (mode & QIODevice::WriteOnly) {
- QWinEventNotifier *n = new WriteOverlappedCompletionNotifier(this, q);
- n->setEnabled(true);
+ initializeOverlappedStructure(communicationOverlapped);
+ if (!::WaitCommEvent(descriptor, &triggeredEventMask, &communicationOverlapped)) {
+ const QSerialPort::SerialPortError error = decodeSystemError();
+ if (error != QSerialPort::NoError) {
+ q->setError(decodeSystemError());
+ return false;
+ }
}
- QWinEventNotifier *n = new CommOverlappedEventNotifier(this, originalEventMask, q);
- n->setEnabled(true);
+ communicationNotifier->setEnabled(true);
detectDefaultSettings();
return true;
@@ -332,8 +221,9 @@ void QSerialPortPrivate::close()
if (!::CancelIo(descriptor))
q->setError(decodeSystemError());
- qDeleteAll(notifiers);
- notifiers.clear();
+ readCompletionNotifier->setEnabled(false);
+ writeCompletionNotifier->setEnabled(false);
+ communicationNotifier->setEnabled(false);
readBuffer.clear();
@@ -502,28 +392,28 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
do {
bool timedOut = false;
- AbstractOverlappedEventNotifier *n = 0;
+ HANDLE triggeredEvent = 0;
- if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &n) || !n) {
+ if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &triggeredEvent) || !triggeredEvent) {
// This is occur timeout or another error
if (!timedOut)
q->setError(decodeSystemError());
return false;
}
- switch (n->type()) {
- case AbstractOverlappedEventNotifier::CommEvent:
- if (!n->processCompletionRoutine())
+ if (triggeredEvent == communicationOverlapped.hEvent) {
+ _q_canCompleteCommunication();
+ if (error != QSerialPort::NoError)
return false;
- break;
- case AbstractOverlappedEventNotifier::ReadCompletionEvent:
- return n->processCompletionRoutine();
- case AbstractOverlappedEventNotifier::WriteCompletionEvent:
- n->processCompletionRoutine();
- break;
- default: // newer called
+ } else if (triggeredEvent == readCompletionOverlapped.hEvent) {
+ _q_canCompleteRead();
+ return error == QSerialPort::NoError;
+ } else if (triggeredEvent == writeCompletionOverlapped.hEvent) {
+ _q_canCompleteWrite();
+ } else {
return false;
}
+
} while (msecs == -1 || timeoutValue(msecs, stopWatch.elapsed()) > 0);
return false;
@@ -541,25 +431,25 @@ bool QSerialPortPrivate::waitForBytesWritten(int msecs)
forever {
bool timedOut = false;
- AbstractOverlappedEventNotifier *n = 0;
+ HANDLE triggeredEvent = 0;
- if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &n) || !n) {
+ if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &triggeredEvent) || !triggeredEvent) {
if (!timedOut)
q->setError(decodeSystemError());
return false;
}
- switch (n->type()) {
- case AbstractOverlappedEventNotifier::CommEvent:
- // do nothing, jump to ReadCompletionEvent case
- case AbstractOverlappedEventNotifier::ReadCompletionEvent:
- n->processCompletionRoutine();
- break;
- case AbstractOverlappedEventNotifier::WriteCompletionEvent:
- return n->processCompletionRoutine();
- default: // newer called
+ if (triggeredEvent == communicationOverlapped.hEvent) {
+ _q_canCompleteRead();
+ } else if (triggeredEvent == readCompletionOverlapped.hEvent) {
+ _q_canCompleteRead();
+ } else if (triggeredEvent == writeCompletionOverlapped.hEvent) {
+ _q_canCompleteWrite();
+ return error == QSerialPort::NoError;
+ } else {
return false;
}
+
}
return false;
@@ -663,6 +553,75 @@ bool QSerialPortPrivate::setDataErrorPolicy(QSerialPort::DataErrorPolicy policy)
#ifndef Q_OS_WINCE
+void QSerialPortPrivate::_q_canCompleteCommunication()
+{
+ Q_Q(QSerialPort);
+
+ DWORD numberOfBytesTransferred = 0;
+
+ if (!::GetOverlappedResult(descriptor, &communicationOverlapped, &numberOfBytesTransferred, FALSE))
+ q->setError(decodeSystemError());
+
+ bool error = false;
+
+ // Check for unexpected event. This event triggered when pulled previously
+ // opened device from the system, when opened as for not to read and not to
+ // write options and so forth.
+ if (triggeredEventMask == 0)
+ error = true;
+
+ // Workaround for standard CDC ACM serial ports, for which triggered an
+ // unexpected event EV_TXEMPTY at data transmission.
+ if ((originalEventMask & triggeredEventMask) == 0) {
+ if ((triggeredEventMask & EV_TXEMPTY) == 0)
+ error = true;
+ }
+
+ // Start processing a caught error.
+ if (error || (EV_ERR & triggeredEventMask))
+ processIoErrors(error);
+
+ if (!error)
+ startAsyncRead();
+}
+
+void QSerialPortPrivate::_q_canCompleteRead()
+{
+ Q_Q(QSerialPort);
+
+ DWORD numberOfBytesTransferred = 0;
+ if (!::GetOverlappedResult(descriptor, &readCompletionOverlapped, &numberOfBytesTransferred, FALSE))
+ q->setError(decodeSystemError());
+
+ completeAsyncRead(numberOfBytesTransferred);
+
+ // start async read for possible remainder into driver queue
+ if ((numberOfBytesTransferred > 0) && (policy == QSerialPort::IgnorePolicy)) {
+ startAsyncRead();
+ } else { // driver queue is emplty, so startup wait comm event
+ initializeOverlappedStructure(communicationOverlapped);
+ if (!::WaitCommEvent(descriptor, &triggeredEventMask, &communicationOverlapped)) {
+ const QSerialPort::SerialPortError error = decodeSystemError();
+ if (error != QSerialPort::NoError) {
+ q->setError(decodeSystemError());
+ }
+ }
+ }
+}
+
+void QSerialPortPrivate::_q_canCompleteWrite()
+{
+ Q_Q(QSerialPort);
+
+ DWORD numberOfBytesTransferred = 0;
+ if (!::GetOverlappedResult(descriptor, &writeCompletionOverlapped, &numberOfBytesTransferred, FALSE)) {
+ numberOfBytesTransferred = 0;
+ q->setError(decodeSystemError());
+ }
+
+ completeAsyncWrite(numberOfBytesTransferred);
+}
+
bool QSerialPortPrivate::startAsyncRead()
{
Q_Q(QSerialPort);
@@ -678,14 +637,8 @@ bool QSerialPortPrivate::startAsyncRead()
}
}
- AbstractOverlappedEventNotifier *n = lookupReadCompletionNotifier();
- if (!n) {
- q->setError(QSerialPort::ResourceError);
- return false;
- }
-
- initializeOverlappedStructure(*n->overlappedPointer());
- if (::ReadFile(descriptor, readChunkBuffer.data(), bytesToRead, NULL, n->overlappedPointer()))
+ initializeOverlappedStructure(readCompletionOverlapped);
+ if (::ReadFile(descriptor, readChunkBuffer.data(), bytesToRead, NULL, &readCompletionOverlapped))
return true;
QSerialPort::SerialPortError error = decodeSystemError();
@@ -716,14 +669,8 @@ bool QSerialPortPrivate::startAsyncWrite(int maxSize)
writeSequenceStarted = true;
- AbstractOverlappedEventNotifier *n = lookupWriteCompletionNotifier();
- if (!n) {
- q->setError(QSerialPort::ResourceError);
- return false;
- }
-
- initializeOverlappedStructure(*n->overlappedPointer());
- if (::WriteFile(descriptor, ptr, nextSize, NULL, n->overlappedPointer()))
+ initializeOverlappedStructure(writeCompletionOverlapped);
+ if (::WriteFile(descriptor, ptr, nextSize, NULL, &writeCompletionOverlapped))
return true;
QSerialPort::SerialPortError error = decodeSystemError();
@@ -828,33 +775,6 @@ void QSerialPortPrivate::completeAsyncWrite(DWORD numberOfBytes)
startAsyncWrite(WriteChunkSize);
}
-AbstractOverlappedEventNotifier *QSerialPortPrivate::lookupWriteCompletionNotifier()
-{
- foreach (AbstractOverlappedEventNotifier *n, notifiers) {
- if (n->type() == AbstractOverlappedEventNotifier::WriteCompletionEvent)
- return n;
- }
- return 0;
-}
-
-AbstractOverlappedEventNotifier *QSerialPortPrivate::lookupCommEventNotifier()
-{
- foreach (AbstractOverlappedEventNotifier *n, notifiers) {
- if (n->type() == AbstractOverlappedEventNotifier::CommEvent)
- return n;
- }
- return 0;
-}
-
-AbstractOverlappedEventNotifier *QSerialPortPrivate::lookupReadCompletionNotifier()
-{
- foreach (AbstractOverlappedEventNotifier *n, notifiers) {
- if (n->type() == AbstractOverlappedEventNotifier::ReadCompletionEvent)
- return n;
- }
- return 0;
-}
-
bool QSerialPortPrivate::updateDcb()
{
Q_Q(QSerialPort);
@@ -991,14 +911,17 @@ QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
#ifndef Q_OS_WINCE
-bool QSerialPortPrivate::waitAnyEvent(int msecs, bool *timedOut,
- AbstractOverlappedEventNotifier **triggeredNotifier)
+bool QSerialPortPrivate::waitAnyEvent(int msecs, bool *timedOut, HANDLE *triggeredEvent)
{
Q_Q(QSerialPort);
Q_ASSERT(timedOut);
- QVector<HANDLE> handles = notifiers.keys().toVector();
+ QVector<HANDLE> handles = QVector<HANDLE>()
+ << communicationOverlapped.hEvent
+ << readCompletionOverlapped.hEvent
+ << writeCompletionOverlapped.hEvent;
+
DWORD waitResult = ::WaitForMultipleObjects(handles.count(),
handles.constData(),
FALSE, // wait any event
@@ -1012,8 +935,7 @@ bool QSerialPortPrivate::waitAnyEvent(int msecs, bool *timedOut,
if (waitResult >= DWORD(WAIT_OBJECT_0 + handles.count()))
return false;
- HANDLE h = handles.at(waitResult - WAIT_OBJECT_0);
- *triggeredNotifier = notifiers.value(h);
+ *triggeredEvent = handles.at(waitResult - WAIT_OBJECT_0);
return true;
}
@@ -1132,13 +1054,6 @@ QList<qint32> QSerialPortPrivate::standardBaudRates()
return standardBaudRatePairList();
}
-void QSerialPortPrivate::setError(QSerialPort::SerialPortError serialPortError, const QString &errorString)
-{
- Q_Q(QSerialPort);
-
- q->setError(serialPortError, errorString);
-}
-
QSerialPort::Handle QSerialPort::handle() const
{
Q_D(const QSerialPort);
diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h
index a528f28..059be87 100644
--- a/src/serialport/qserialport_win_p.h
+++ b/src/serialport/qserialport_win_p.h
@@ -57,10 +57,6 @@ QT_BEGIN_NAMESPACE
class QThread;
#endif
-#ifndef Q_OS_WINCE
-class AbstractOverlappedEventNotifier;
-#endif
-
class QSerialPortPrivate : public QSerialPortPrivateData
{
Q_DECLARE_PUBLIC(QSerialPort)
@@ -98,16 +94,16 @@ public:
bool setDataErrorPolicy(QSerialPort::DataErrorPolicy policy);
void processIoErrors(bool error);
- void setError(QSerialPort::SerialPortError error, const QString &errorString = QString());
QSerialPort::SerialPortError decodeSystemError() const;
#ifndef Q_OS_WINCE
+ void _q_canCompleteCommunication();
+ void _q_canCompleteRead();
+ void _q_canCompleteWrite();
+
bool startAsyncRead();
bool startAsyncWrite(int maxSize = INT_MAX);
void completeAsyncRead(DWORD numberOfBytes);
void completeAsyncWrite(DWORD numberOfBytes);
- AbstractOverlappedEventNotifier *lookupWriteCompletionNotifier();
- AbstractOverlappedEventNotifier *lookupCommEventNotifier();
- AbstractOverlappedEventNotifier *lookupReadCompletionNotifier();
#else
bool notifyRead();
bool notifyWrite(int maxSize = INT_MAX);
@@ -129,12 +125,19 @@ public:
bool parityErrorOccurred;
#ifndef Q_OS_WINCE
- QHash<HANDLE, AbstractOverlappedEventNotifier *> notifiers;
QByteArray readChunkBuffer;
qint64 actualWriteBufferSize;
qint64 acyncWritePosition;
bool readyReadEmitted;
bool writeSequenceStarted;
+ QWinEventNotifier *communicationNotifier;
+ QWinEventNotifier *readCompletionNotifier;
+ QWinEventNotifier *writeCompletionNotifier;
+ OVERLAPPED communicationOverlapped;
+ OVERLAPPED readCompletionOverlapped;
+ OVERLAPPED writeCompletionOverlapped;
+ DWORD originalEventMask;
+ DWORD triggeredEventMask;
#else
QThread *eventNotifier;
QMutex settingsChangeMutex;
@@ -147,8 +150,7 @@ private:
void detectDefaultSettings();
#ifndef Q_OS_WINCE
- bool waitAnyEvent(int msecs, bool *timedOut,
- AbstractOverlappedEventNotifier **triggeredNotifier);
+ bool waitAnyEvent(int msecs, bool *timedOut, HANDLE *triggeredEvent);
#else
bool waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,