QEventDispatcherGlib: do not omit active notifiers on source dispatching

It is quite common for a socket notifier to be disabled in a slot
connected to its activated() signal. But the event dispatcher did not
update the position in the list of registered notifiers, which caused
the next notifier to be omitted. Of course, on the next iteration of
the event loop, the omitted notifier would fire again, but this reduced
the scalability of applications that use a large number of sockets.

To solve the problem, we update the current position in the list when
a notifier becomes unregistered.

Change-Id: I6565bf23500d9e38ce84b34784d89d227fa166e1
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Alex Trotsenko 2021-01-27 16:18:11 +02:00 committed by Oswald Buddenhagen
parent f9896cb3cd
commit 8f9222db3b

View File

@ -62,6 +62,7 @@ struct GSocketNotifierSource
{
GSource source;
QList<GPollFDWithQSocketNotifier *> pollfds;
int activeNotifierPos;
};
static gboolean socketNotifierSourcePrepare(GSource *, gint *timeout)
@ -100,8 +101,9 @@ static gboolean socketNotifierSourceDispatch(GSource *source, GSourceFunc, gpoin
QEvent event(QEvent::SockAct);
GSocketNotifierSource *src = reinterpret_cast<GSocketNotifierSource *>(source);
for (int i = 0; i < src->pollfds.count(); ++i) {
GPollFDWithQSocketNotifier *p = src->pollfds.at(i);
for (src->activeNotifierPos = 0; src->activeNotifierPos < src->pollfds.count();
++src->activeNotifierPos) {
GPollFDWithQSocketNotifier *p = src->pollfds.at(src->activeNotifierPos);
if ((p->pollfd.revents & p->pollfd.events) != 0)
QCoreApplication::sendEvent(p->socketNotifier, &event);
@ -501,6 +503,10 @@ void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier)
d->socketNotifierSource->pollfds.removeAt(i);
delete p;
// Keep a position in the list for the next item.
if (i <= d->socketNotifierSource->activeNotifierPos)
--d->socketNotifierSource->activeNotifierPos;
return;
}
}