summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/serialport/qwinoverlappedionotifier.cpp24
1 files changed, 21 insertions, 3 deletions
diff --git a/src/serialport/qwinoverlappedionotifier.cpp b/src/serialport/qwinoverlappedionotifier.cpp
index d03b52ae..65d63bba 100644
--- a/src/serialport/qwinoverlappedionotifier.cpp
+++ b/src/serialport/qwinoverlappedionotifier.cpp
@@ -93,6 +93,7 @@ public:
HANDLE hSemaphore = nullptr;
HANDLE hResultsMutex = nullptr;
QAtomicInt waiting;
+ QAtomicInt signalSent;
QQueue<IOResult> results;
};
@@ -361,14 +362,31 @@ void QWinOverlappedIoNotifierPrivate::notify(DWORD numberOfBytes, DWORD errorCod
results.enqueue(IOResult(numberOfBytes, errorCode, overlapped));
ReleaseMutex(hResultsMutex);
ReleaseSemaphore(hSemaphore, 1, NULL);
- if (!waiting)
+ // Do not send a signal if we didn't process the previous one.
+ // This is done to prevent soft memory leaks when working in a completely
+ // synchronous way.
+ if (!waiting && !signalSent.loadAcquire()) {
+ signalSent.storeRelease(1);
emit q->_q_notify();
+ }
}
void QWinOverlappedIoNotifierPrivate::_q_notified()
{
- if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0)
- dispatchNextIoResult();
+ Q_Q(QWinOverlappedIoNotifier);
+ signalSent.storeRelease(0); // signal processed - ready for a new one
+ if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0) {
+ // As we do not queue signals anymore, we need to process the whole
+ // queue at once.
+ WaitForSingleObject(hResultsMutex, INFINITE);
+ QQueue<IOResult> values;
+ results.swap(values);
+ ReleaseMutex(hResultsMutex);
+ while (!values.empty()) {
+ IOResult ioresult = values.dequeue();
+ emit q->notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped);
+ }
+ }
}
OVERLAPPED *QWinOverlappedIoNotifierPrivate::dispatchNextIoResult()