264QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
265 : mainContext(context)
267#if GLIB_MAJOR_VERSION == 2
&& GLIB_MINOR_VERSION < 32
268 if (qEnvironmentVariableIsEmpty(
"QT_NO_THREADED_GLIB")) {
269 Q_CONSTINIT
static QBasicMutex mutex;
270 QMutexLocker locker(&mutex);
271 if (!g_thread_supported())
277 g_main_context_ref(mainContext);
279 QCoreApplication *app = QCoreApplication::instance();
280 if (app && QThread::currentThread() == app->thread()) {
281 mainContext = g_main_context_default();
282 g_main_context_ref(mainContext);
284 mainContext = g_main_context_new();
288#if GLIB_CHECK_VERSION (2
, 22
, 0
)
289 g_main_context_push_thread_default (mainContext);
293 GSource *source = g_source_new(&postEventSourceFuncs,
sizeof(GPostEventSource));
294 g_source_set_name(source,
"[Qt] GPostEventSource");
295 postEventSource =
reinterpret_cast<GPostEventSource *>(source);
297 postEventSource->serialNumber.storeRelaxed(1);
298 postEventSource->d =
this;
299 g_source_set_can_recurse(&postEventSource->source,
true);
300 g_source_attach(&postEventSource->source, mainContext);
303 source = g_source_new(&socketNotifierSourceFuncs,
sizeof(GSocketNotifierSource));
304 g_source_set_name(source,
"[Qt] GSocketNotifierSource");
305 socketNotifierSource =
reinterpret_cast<GSocketNotifierSource *>(source);
306 (
void)
new (&socketNotifierSource->pollfds) QList<GPollFDWithQSocketNotifier *>();
307 g_source_set_can_recurse(&socketNotifierSource->source,
true);
308 g_source_attach(&socketNotifierSource->source, mainContext);
311 source = g_source_new(&timerSourceFuncs,
sizeof(GTimerSource));
312 g_source_set_name(source,
"[Qt] GTimerSource");
313 timerSource =
reinterpret_cast<GTimerSource *>(source);
314 (
void)
new (&timerSource->timerList) QTimerInfoList();
315 timerSource->processEventsFlags = QEventLoop::AllEvents;
316 timerSource->runWithIdlePriority =
false;
317 g_source_set_can_recurse(&timerSource->source,
true);
318 g_source_attach(&timerSource->source, mainContext);
320 source = g_source_new(&idleTimerSourceFuncs,
sizeof(GIdleTimerSource));
321 g_source_set_name(source,
"[Qt] GIdleTimerSource");
322 idleTimerSource =
reinterpret_cast<GIdleTimerSource *>(source);
323 idleTimerSource->timerSource = timerSource;
324 g_source_set_can_recurse(&idleTimerSource->source,
true);
325 g_source_attach(&idleTimerSource->source, mainContext);
345QEventDispatcherGlib::~QEventDispatcherGlib()
347 Q_D(QEventDispatcherGlib);
350 d->timerSource->timerList.clearTimers();
351 d->timerSource->timerList.~QTimerInfoList();
352 g_source_destroy(&d->timerSource->source);
353 g_source_unref(&d->timerSource->source);
354 d->timerSource =
nullptr;
355 g_source_destroy(&d->idleTimerSource->source);
356 g_source_unref(&d->idleTimerSource->source);
357 d->idleTimerSource =
nullptr;
360 for (qsizetype i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) {
361 GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds.at(i);
362 g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
365 d->socketNotifierSource->pollfds.~QList<GPollFDWithQSocketNotifier *>();
366 g_source_destroy(&d->socketNotifierSource->source);
367 g_source_unref(&d->socketNotifierSource->source);
368 d->socketNotifierSource =
nullptr;
371 g_source_destroy(&d->postEventSource->source);
372 g_source_unref(&d->postEventSource->source);
373 d->postEventSource =
nullptr;
375 Q_ASSERT(d->mainContext !=
nullptr);
376#if GLIB_CHECK_VERSION (2
, 22
, 0
)
377 g_main_context_pop_thread_default (d->mainContext);
379 g_main_context_unref(d->mainContext);
380 d->mainContext =
nullptr;
383bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
385 Q_D(QEventDispatcherGlib);
387 const bool canWait = flags.testAnyFlag(QEventLoop::WaitForMoreEvents);
394 QEventLoop::ProcessEventsFlags savedFlags = d->timerSource->processEventsFlags;
395 d->timerSource->processEventsFlags = flags;
397 if (!(flags & QEventLoop::EventLoopExec)) {
399 d->timerSource->runWithIdlePriority =
false;
402 bool result = g_main_context_iteration(d->mainContext, canWait);
403 while (!result && canWait)
404 result = g_main_context_iteration(d->mainContext, canWait);
406 d->timerSource->processEventsFlags = savedFlags;
414void QEventDispatcherGlib::registerSocketNotifier(QSocketNotifier *notifier)
417 int sockfd =
int(notifier->socket());
418 const auto type = notifier->type();
421 qWarning(
"QSocketNotifier: Internal error");
423 }
else if (notifier->thread() != thread()
424 || thread() != QThread::currentThread()) {
425 qWarning(
"QSocketNotifier: socket notifiers cannot be enabled from another thread");
430 Q_D(QEventDispatcherGlib);
433 GPollFDWithQSocketNotifier *p =
new GPollFDWithQSocketNotifier;
434 p->pollfd.fd = sockfd;
436 case QSocketNotifier::Read:
437 p->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
439 case QSocketNotifier::Write:
440 p->pollfd.events = G_IO_OUT | G_IO_HUP | G_IO_ERR;
442 case QSocketNotifier::Exception:
443 p->pollfd.events = G_IO_PRI | G_IO_HUP | G_IO_ERR;
446 p->socketNotifier = notifier;
448 d->socketNotifierSource->pollfds.append(p);
450 g_source_add_poll(&d->socketNotifierSource->source, &p->pollfd);
453void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier)
457 if (notifier->socket() < 0) {
458 qWarning(
"QSocketNotifier: Internal error");
460 }
else if (notifier->thread() != thread()
461 || thread() != QThread::currentThread()) {
462 qWarning(
"QSocketNotifier: socket notifiers cannot be disabled from another thread");
467 Q_D(QEventDispatcherGlib);
469 for (qsizetype i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) {
470 GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds.at(i);
471 if (p->socketNotifier == notifier) {
473 g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
475 d->socketNotifierSource->pollfds.removeAt(i);
479 if (i <= d->socketNotifierSource->activeNotifierPos)
480 --d->socketNotifierSource->activeNotifierPos;
487void QEventDispatcherGlib::registerTimer(Qt::TimerId timerId, Duration interval,
488 Qt::TimerType timerType, QObject *object)
491 if (qToUnderlying(timerId) < 1 || interval < 0ns || !object) {
492 qWarning(
"QEventDispatcherGlib::registerTimer: invalid arguments");
494 }
else if (object->thread() != thread() || thread() != QThread::currentThread()) {
495 qWarning(
"QEventDispatcherGlib::registerTimer: timers cannot be started from another thread");
500 Q_D(QEventDispatcherGlib);
501 d->timerSource->timerList.registerTimer(timerId, interval, timerType, object);
QEventDispatcherGlibPrivate * d