summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Trotsenko <alex1973tr@gmail.com>2021-03-24 20:56:06 +0200
committerAlex Trotsenko <alex1973tr@gmail.com>2021-03-31 22:52:22 +0300
commit007addc0cc3fb5d5e06fa8490f5247e064d6f8b0 (patch)
treee08411177c9dbe513c5a99bef458b3c2f7082935
parent8f6d8d7cd8eb72570cef91bd00b982d161bb0afd (diff)
QWinEventNotifier: migrate to new thread pool API
Change-Id: I2fb1ba7254ecfd502a22c706404f92dd1bc3a584 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp70
-rw-r--r--src/corelib/kernel/qwineventnotifier_p.h15
2 files changed, 47 insertions, 38 deletions
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index f9e91e73d7..3371e101b6 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -117,10 +117,7 @@ QWinEventNotifier::QWinEventNotifier(QObject *parent)
QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent)
: QObject(*new QWinEventNotifierPrivate(hEvent, false), parent)
{
- Q_D(QWinEventNotifier);
-
- d->registerWaitObject();
- d->enabled = true;
+ setEnabled(true);
}
/*!
@@ -198,9 +195,20 @@ void QWinEventNotifier::setEnabled(bool enable)
// event shall be ignored.
d->winEventActPosted.testAndSetRelaxed(QWinEventNotifierPrivate::Posted,
QWinEventNotifierPrivate::IgnorePosted);
- d->registerWaitObject();
- } else if (d->waitHandle != NULL) {
- d->unregisterWaitObject();
+ // The notifier can't be registered, if 'enabled' flag was false.
+ // The code in the else branch ensures that.
+ Q_ASSERT(!d->registered);
+ SetThreadpoolWait(d->waitObject, d->handleToEvent, NULL);
+ d->registered = true;
+ } else if (d->registered) {
+ // Stop waiting for an event. However, there may be a callback queued
+ // already after the call.
+ SetThreadpoolWait(d->waitObject, NULL, NULL);
+ // So, to avoid a race condition after a possible call to
+ // setEnabled(true), wait for a possibly outstanding callback
+ // to complete.
+ WaitForThreadpoolWaitCallbacks(d->waitObject, TRUE);
+ d->registered = false;
}
}
@@ -226,12 +234,16 @@ bool QWinEventNotifier::event(QEvent * e)
// again.
if (d->winEventActPosted.fetchAndStoreRelaxed(QWinEventNotifierPrivate::NotPosted)
== QWinEventNotifierPrivate::Posted && d->enabled) {
- d->unregisterWaitObject();
+ // Clear the flag, as the wait object is implicitly unregistered
+ // when the callback is queued.
+ d->registered = false;
emit activated(d->handleToEvent, QPrivateSignal());
- if (d->enabled && d->waitHandle == NULL)
- d->registerWaitObject();
+ if (d->enabled && !d->registered) {
+ SetThreadpoolWait(d->waitObject, d->handleToEvent, NULL);
+ d->registered = true;
+ }
}
return true;
default:
@@ -240,8 +252,25 @@ bool QWinEventNotifier::event(QEvent * e)
return QObject::event(e);
}
-void CALLBACK QWinEventNotifierPrivate::wfsoCallback(void *context, BOOLEAN /*ignore*/)
+QWinEventNotifierPrivate::QWinEventNotifierPrivate(HANDLE h, bool e)
+ : handleToEvent(h), enabled(e), registered(false)
+{
+ waitObject = CreateThreadpoolWait(waitCallback, this, NULL);
+ if (waitObject == NULL)
+ qErrnoWarning("QWinEventNotifier:: CreateThreadpollWait failed.");
+}
+
+QWinEventNotifierPrivate::~QWinEventNotifierPrivate()
+{
+ CloseThreadpoolWait(waitObject);
+}
+
+void QWinEventNotifierPrivate::waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
+ PTP_WAIT wait, TP_WAIT_RESULT waitResult)
{
+ Q_UNUSED(instance);
+ Q_UNUSED(wait);
+ Q_UNUSED(waitResult);
QWinEventNotifierPrivate *nd = reinterpret_cast<QWinEventNotifierPrivate *>(context);
// Do not post an event, if an event is already in the message queue. Note
@@ -252,23 +281,4 @@ void CALLBACK QWinEventNotifierPrivate::wfsoCallback(void *context, BOOLEAN /*ig
}
}
-bool QWinEventNotifierPrivate::registerWaitObject()
-{
- if (RegisterWaitForSingleObject(&waitHandle, handleToEvent, wfsoCallback, this,
- INFINITE, WT_EXECUTEONLYONCE) == 0) {
- qErrnoWarning("QWinEventNotifier: RegisterWaitForSingleObject failed.");
- return false;
- }
- return true;
-}
-
-void QWinEventNotifierPrivate::unregisterWaitObject()
-{
- // Unregister the wait handle and wait for pending callbacks to finish.
- if (UnregisterWaitEx(waitHandle, INVALID_HANDLE_VALUE))
- waitHandle = NULL;
- else
- qErrnoWarning("QWinEventNotifier: UnregisterWaitEx failed.");
-}
-
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qwineventnotifier_p.h b/src/corelib/kernel/qwineventnotifier_p.h
index da9d8ff9a0..4e402ec826 100644
--- a/src/corelib/kernel/qwineventnotifier_p.h
+++ b/src/corelib/kernel/qwineventnotifier_p.h
@@ -63,21 +63,20 @@ class QWinEventNotifierPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QWinEventNotifier)
public:
- QWinEventNotifierPrivate()
- : handleToEvent(0), enabled(false) {}
- QWinEventNotifierPrivate(HANDLE h, bool e)
- : handleToEvent(h), enabled(e) {}
+ QWinEventNotifierPrivate() : QWinEventNotifierPrivate(0, false) {}
+ QWinEventNotifierPrivate(HANDLE h, bool e);
+ virtual ~QWinEventNotifierPrivate();
- static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/);
- bool registerWaitObject();
- void unregisterWaitObject();
+ static void CALLBACK waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
+ PTP_WAIT wait, TP_WAIT_RESULT waitResult);
HANDLE handleToEvent;
- HANDLE waitHandle = NULL;
+ PTP_WAIT waitObject = NULL;
enum PostingState { NotPosted = 0, Posted, IgnorePosted };
QAtomicInt winEventActPosted;
bool enabled;
+ bool registered;
};
QT_END_NAMESPACE