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 +#include #include #include #include @@ -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 results; }; @@ -286,6 +289,47 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled) d->iocp->unregisterNotifier(d); } +OVERLAPPED *QWinOverlappedIoNotifierPrivate::waitForAnyNotified(int msecs) +{ + if (!iocp->isRunning()) { + qWarning("Called QWinOverlappedIoNotifier::waitForAnyNotified on inactive notifier."); + return 0; + } + + if (msecs == 0) + iocp->drainQueue(); + + const DWORD wfso = WaitForSingleObject(hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs)); + switch (wfso) { + case WAIT_OBJECT_0: + ReleaseSemaphore(hSemaphore, 1, NULL); + return _q_notified(); + case WAIT_TIMEOUT: + return 0; + default: + qErrnoWarning("QWinOverlappedIoNotifier::waitForAnyNotified: WaitForSingleObject failed."); + return 0; + } +} + +class QScopedAtomicIntIncrementor +{ +public: + QScopedAtomicIntIncrementor(QAtomicInt &i) + : m_int(i) + { + ++m_int; + } + + ~QScopedAtomicIntIncrementor() + { + --m_int; + } + +private: + QAtomicInt &m_int; +}; + /*! * Wait synchronously for any notified signal. * @@ -296,24 +340,9 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled) OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs) { Q_D(QWinOverlappedIoNotifier); - if (!d->iocp->isRunning()) { - qWarning("Called QWinOverlappedIoNotifier::waitForAnyNotified on inactive notifier."); - return 0; - } - - if (msecs == 0) - d->iocp->drainQueue(); - - switch (WaitForSingleObject(d->hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs))) { - case WAIT_OBJECT_0: - ReleaseSemaphore(d->hSemaphore, 1, NULL); - return d->_q_notified(); - case WAIT_TIMEOUT: - return 0; - default: - qErrnoWarning("QWinOverlappedIoNotifier::waitForAnyNotified: WaitForSingleObject failed."); - return 0; - } + QScopedAtomicIntIncrementor saii(d->waiting); + OVERLAPPED *result = d->waitForAnyNotified(msecs); + return result; } /*! @@ -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()