Fix QWinEventNotifier for auto-reset events

Auto-reset events are automatically reset to non-signaled when we get
notified about the signaled state. This implies that we cannot check the
event state again in activateEventNotifiers. Instead, store the signaled
state in a QAtomicInt and test and decrement that.

This amends commit 85403d0a.

Task-number: QTBUG-63555
Change-Id: I0adee3d2929783f98d91060f9106c8b5266d72fa
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
This commit is contained in:
Joerg Bornemann 2017-10-06 13:09:57 +02:00 committed by André Hartmann
parent 1a039e89be
commit b5f2bf1a71
4 changed files with 16 additions and 2 deletions

View File

@ -942,7 +942,8 @@ void QEventDispatcherWin32::activateEventNotifiers()
for (int i = d->winEventNotifierList.count(); --i >= 0;) { for (int i = d->winEventNotifierList.count(); --i >= 0;) {
QWinEventNotifier *notifier = d->winEventNotifierList.at(i); QWinEventNotifier *notifier = d->winEventNotifierList.at(i);
QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier); QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
if (WaitForSingleObject(nd->handleToEvent, 0) == WAIT_OBJECT_0) { if (nd->signaledCount.load() != 0) {
--nd->signaledCount;
nd->unregisterWaitObject(); nd->unregisterWaitObject();
d->activateEventNotifier(notifier); d->activateEventNotifier(notifier);
} }

View File

@ -157,6 +157,7 @@ void QWinEventNotifier::setHandle(HANDLE hEvent)
Q_D(QWinEventNotifier); Q_D(QWinEventNotifier);
setEnabled(false); setEnabled(false);
d->handleToEvent = hEvent; d->handleToEvent = hEvent;
d->signaledCount = 0;
} }
/*! /*!
@ -254,6 +255,7 @@ static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/)
QAbstractEventDispatcher *eventDispatcher = nd->threadData->eventDispatcher.load(); QAbstractEventDispatcher *eventDispatcher = nd->threadData->eventDispatcher.load();
QEventDispatcherWin32Private *edp = QEventDispatcherWin32Private::get( QEventDispatcherWin32Private *edp = QEventDispatcherWin32Private::get(
static_cast<QEventDispatcherWin32 *>(eventDispatcher)); static_cast<QEventDispatcherWin32 *>(eventDispatcher));
++nd->signaledCount;
SetEvent(edp->winEventNotifierActivatedEvent); SetEvent(edp->winEventNotifierActivatedEvent);
} }

View File

@ -54,6 +54,7 @@
#include "qwineventnotifier.h" #include "qwineventnotifier.h"
#include <private/qobject_p.h> #include <private/qobject_p.h>
#include <QtCore/qatomic.h>
#include <QtCore/qt_windows.h> #include <QtCore/qt_windows.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -73,6 +74,7 @@ public:
HANDLE handleToEvent; HANDLE handleToEvent;
HANDLE waitHandle = NULL; HANDLE waitHandle = NULL;
QAtomicInt signaledCount;
bool enabled; bool enabled;
}; };

View File

@ -41,6 +41,7 @@ protected slots:
void simple_activated(); void simple_activated();
void simple_timerSet(); void simple_timerSet();
private slots: private slots:
void simple_data();
void simple(); void simple();
void manyNotifiers(); void manyNotifiers();
@ -61,9 +62,17 @@ void tst_QWinEventNotifier::simple_timerSet()
SetEvent((HANDLE)simpleHEvent); SetEvent((HANDLE)simpleHEvent);
} }
void tst_QWinEventNotifier::simple_data()
{
QTest::addColumn<bool>("resetManually");
QTest::newRow("manual_reset") << true;
QTest::newRow("auto_reset") << false;
}
void tst_QWinEventNotifier::simple() void tst_QWinEventNotifier::simple()
{ {
simpleHEvent = CreateEvent(0, true, false, 0); QFETCH(bool, resetManually);
simpleHEvent = CreateEvent(0, resetManually, false, 0);
QVERIFY(simpleHEvent); QVERIFY(simpleHEvent);
QWinEventNotifier n(simpleHEvent); QWinEventNotifier n(simpleHEvent);