fix growth of event queue in QWinOverlappedIoNotifier::waitFor*
Do not emit _q_notified when we're in a wait function. Otherwise, the queued signals could pile up in the event queue. Task-number: QTBUG-48653 Change-Id: I071863e2356e17c7004e3b7ca359967cb115e343 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>bb10
parent
b7c4f15d67
commit
c20f92a0fa
|
|
@ -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,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()
|
||||
|
|
|
|||
Loading…
Reference in New Issue