summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/io/qwinoverlappedionotifier.cpp62
1 files changed, 47 insertions, 15 deletions
diff --git a/src/corelib/io/qwinoverlappedionotifier.cpp b/src/corelib/io/qwinoverlappedionotifier.cpp
index 083feb4a20..c6ce15c2c9 100644
--- a/src/corelib/io/qwinoverlappedionotifier.cpp
+++ b/src/corelib/io/qwinoverlappedionotifier.cpp
@@ -33,6 +33,7 @@
#include "qwinoverlappedionotifier_p.h"
#include <qdebug.h>
+#include <qatomic.h>
#include <qelapsedtimer.h>
#include <qmutex.h>
#include <qpointer.h>
@@ -99,6 +100,7 @@ public:
{
}
+ OVERLAPPED *waitForAnyNotified(int msecs);
void notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped);
OVERLAPPED *_q_notified();
@@ -108,6 +110,7 @@ public:
HANDLE hHandle;
HANDLE hSemaphore;
HANDLE hResultsMutex;
+ QAtomicInt waiting;
QQueue<IOResult> results;
};
@@ -286,28 +289,21 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled)
d->iocp->unregisterNotifier(d);
}
-/*!
- * Wait synchronously for any notified signal.
- *
- * The function returns a pointer to the OVERLAPPED object corresponding to the completed I/O
- * operation. In case no I/O operation was completed during the \a msec timeout, this function
- * returns a null pointer.
- */
-OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs)
+OVERLAPPED *QWinOverlappedIoNotifierPrivate::waitForAnyNotified(int msecs)
{
- Q_D(QWinOverlappedIoNotifier);
- if (!d->iocp->isRunning()) {
+ if (!iocp->isRunning()) {
qWarning("Called QWinOverlappedIoNotifier::waitForAnyNotified on inactive notifier.");
return 0;
}
if (msecs == 0)
- d->iocp->drainQueue();
+ iocp->drainQueue();
- switch (WaitForSingleObject(d->hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs))) {
+ const DWORD wfso = WaitForSingleObject(hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs));
+ switch (wfso) {
case WAIT_OBJECT_0:
- ReleaseSemaphore(d->hSemaphore, 1, NULL);
- return d->_q_notified();
+ ReleaseSemaphore(hSemaphore, 1, NULL);
+ return _q_notified();
case WAIT_TIMEOUT:
return 0;
default:
@@ -316,6 +312,39 @@ OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs)
}
}
+class QScopedAtomicIntIncrementor
+{
+public:
+ QScopedAtomicIntIncrementor(QAtomicInt &i)
+ : m_int(i)
+ {
+ ++m_int;
+ }
+
+ ~QScopedAtomicIntIncrementor()
+ {
+ --m_int;
+ }
+
+private:
+ QAtomicInt &m_int;
+};
+
+/*!
+ * Wait synchronously for any notified signal.
+ *
+ * The function returns a pointer to the OVERLAPPED object corresponding to the completed I/O
+ * operation. In case no I/O operation was completed during the \a msec timeout, this function
+ * returns a null pointer.
+ */
+OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs)
+{
+ Q_D(QWinOverlappedIoNotifier);
+ QScopedAtomicIntIncrementor saii(d->waiting);
+ OVERLAPPED *result = d->waitForAnyNotified(msecs);
+ return result;
+}
+
/*!
* Wait synchronously for the notified signal.
*
@@ -324,6 +353,8 @@ OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs)
*/
bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped)
{
+ Q_D(QWinOverlappedIoNotifier);
+ QScopedAtomicIntIncrementor saii(d->waiting);
int t = msecs;
QElapsedTimer stopWatch;
stopWatch.start();
@@ -350,7 +381,8 @@ void QWinOverlappedIoNotifierPrivate::notify(DWORD numberOfBytes, DWORD errorCod
results.enqueue(IOResult(numberOfBytes, errorCode, overlapped));
ReleaseMutex(hResultsMutex);
ReleaseSemaphore(hSemaphore, 1, NULL);
- emit q->_q_notify();
+ if (!waiting)
+ emit q->_q_notify();
}
OVERLAPPED *QWinOverlappedIoNotifierPrivate::_q_notified()