diff options
author | Alex Trotsenko <alex1973tr@gmail.com> | 2021-03-24 20:56:06 +0200 |
---|---|---|
committer | Alex Trotsenko <alex1973tr@gmail.com> | 2021-03-31 22:52:22 +0300 |
commit | 007addc0cc3fb5d5e06fa8490f5247e064d6f8b0 (patch) | |
tree | e08411177c9dbe513c5a99bef458b3c2f7082935 | |
parent | 8f6d8d7cd8eb72570cef91bd00b982d161bb0afd (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.cpp | 70 | ||||
-rw-r--r-- | src/corelib/kernel/qwineventnotifier_p.h | 15 |
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 |