QWinEventNotifier: migrate to new thread pool API
Change-Id: I2fb1ba7254ecfd502a22c706404f92dd1bc3a584 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
This commit is contained in:
parent
8f6d8d7cd8
commit
007addc0cc
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user