262QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
263 : mainContext(context)
265#if GLIB_MAJOR_VERSION == 2
&& GLIB_MINOR_VERSION < 32
266 if (qEnvironmentVariableIsEmpty(
"QT_NO_THREADED_GLIB")) {
267 Q_CONSTINIT
static QBasicMutex mutex;
268 QMutexLocker locker(&mutex);
269 if (!g_thread_supported())
275 g_main_context_ref(mainContext);
277 QCoreApplication *app = QCoreApplication::instance();
278 if (app && QThread::currentThread() == app->thread()) {
279 mainContext = g_main_context_default();
280 g_main_context_ref(mainContext);
282 mainContext = g_main_context_new();
286#if GLIB_CHECK_VERSION (2
, 22
, 0
)
287 g_main_context_push_thread_default (mainContext);
291 GSource *source = g_source_new(&postEventSourceFuncs,
sizeof(GPostEventSource));
292 g_source_set_name(source,
"[Qt] GPostEventSource");
293 postEventSource =
reinterpret_cast<GPostEventSource *>(source);
295 postEventSource->serialNumber.storeRelaxed(1);
296 postEventSource->d =
this;
297 g_source_set_can_recurse(&postEventSource->source,
true);
298 g_source_attach(&postEventSource->source, mainContext);
301 source = g_source_new(&socketNotifierSourceFuncs,
sizeof(GSocketNotifierSource));
302 g_source_set_name(source,
"[Qt] GSocketNotifierSource");
303 socketNotifierSource =
reinterpret_cast<GSocketNotifierSource *>(source);
304 (
void)
new (&socketNotifierSource->pollfds) QList<GPollFDWithQSocketNotifier *>();
305 g_source_set_can_recurse(&socketNotifierSource->source,
true);
306 g_source_attach(&socketNotifierSource->source, mainContext);
309 source = g_source_new(&timerSourceFuncs,
sizeof(GTimerSource));
310 g_source_set_name(source,
"[Qt] GTimerSource");
311 timerSource =
reinterpret_cast<GTimerSource *>(source);
312 (
void)
new (&timerSource->timerList) QTimerInfoList();
313 timerSource->processEventsFlags = QEventLoop::AllEvents;
314 timerSource->runWithIdlePriority =
false;
315 g_source_set_can_recurse(&timerSource->source,
true);
316 g_source_attach(&timerSource->source, mainContext);
318 source = g_source_new(&idleTimerSourceFuncs,
sizeof(GIdleTimerSource));
319 g_source_set_name(source,
"[Qt] GIdleTimerSource");
320 idleTimerSource =
reinterpret_cast<GIdleTimerSource *>(source);
321 idleTimerSource->timerSource = timerSource;
322 g_source_set_can_recurse(&idleTimerSource->source,
true);
323 g_source_attach(&idleTimerSource->source, mainContext);
343QEventDispatcherGlib::~QEventDispatcherGlib()
345 Q_D(QEventDispatcherGlib);
348 d->timerSource->timerList.clearTimers();
349 d->timerSource->timerList.~QTimerInfoList();
350 g_source_destroy(&d->timerSource->source);
351 g_source_unref(&d->timerSource->source);
352 d->timerSource =
nullptr;
353 g_source_destroy(&d->idleTimerSource->source);
354 g_source_unref(&d->idleTimerSource->source);
355 d->idleTimerSource =
nullptr;
358 for (qsizetype i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) {
359 GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds.at(i);
360 g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
363 d->socketNotifierSource->pollfds.~QList<GPollFDWithQSocketNotifier *>();
364 g_source_destroy(&d->socketNotifierSource->source);
365 g_source_unref(&d->socketNotifierSource->source);
366 d->socketNotifierSource =
nullptr;
369 g_source_destroy(&d->postEventSource->source);
370 g_source_unref(&d->postEventSource->source);
371 d->postEventSource =
nullptr;
373 Q_ASSERT(d->mainContext !=
nullptr);
374#if GLIB_CHECK_VERSION (2
, 22
, 0
)
375 g_main_context_pop_thread_default (d->mainContext);
377 g_main_context_unref(d->mainContext);
378 d->mainContext =
nullptr;
381bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
383 Q_D(QEventDispatcherGlib);
385 const bool canWait = flags.testAnyFlag(QEventLoop::WaitForMoreEvents);
392 QEventLoop::ProcessEventsFlags savedFlags = d->timerSource->processEventsFlags;
393 d->timerSource->processEventsFlags = flags;
395 if (!(flags & QEventLoop::EventLoopExec)) {
397 d->timerSource->runWithIdlePriority =
false;
400 bool result = g_main_context_iteration(d->mainContext, canWait);
401 while (!result && canWait)
402 result = g_main_context_iteration(d->mainContext, canWait);
404 d->timerSource->processEventsFlags = savedFlags;
412void QEventDispatcherGlib::registerSocketNotifier(QSocketNotifier *notifier)
415 int sockfd =
int(notifier->socket());
416 const auto type = notifier->type();
419 qWarning(
"QSocketNotifier: Internal error");
421 }
else if (notifier->thread() != thread()
422 || thread() != QThread::currentThread()) {
423 qWarning(
"QSocketNotifier: socket notifiers cannot be enabled from another thread");
428 Q_D(QEventDispatcherGlib);
431 GPollFDWithQSocketNotifier *p =
new GPollFDWithQSocketNotifier;
432 p->pollfd.fd = sockfd;
434 case QSocketNotifier::Read:
435 p->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
437 case QSocketNotifier::Write:
438 p->pollfd.events = G_IO_OUT | G_IO_HUP | G_IO_ERR;
440 case QSocketNotifier::Exception:
441 p->pollfd.events = G_IO_PRI | G_IO_HUP | G_IO_ERR;
444 p->socketNotifier = notifier;
446 d->socketNotifierSource->pollfds.append(p);
448 g_source_add_poll(&d->socketNotifierSource->source, &p->pollfd);
451void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier)
455 if (notifier->socket() < 0) {
456 qWarning(
"QSocketNotifier: Internal error");
458 }
else if (notifier->thread() != thread()
459 || thread() != QThread::currentThread()) {
460 qWarning(
"QSocketNotifier: socket notifiers cannot be disabled from another thread");
465 Q_D(QEventDispatcherGlib);
467 for (qsizetype i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) {
468 GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds.at(i);
469 if (p->socketNotifier == notifier) {
471 g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
473 d->socketNotifierSource->pollfds.removeAt(i);
477 if (i <= d->socketNotifierSource->activeNotifierPos)
478 --d->socketNotifierSource->activeNotifierPos;
485void QEventDispatcherGlib::registerTimer(Qt::TimerId timerId, Duration interval,
486 Qt::TimerType timerType, QObject *object)
489 if (qToUnderlying(timerId) < 1 || interval < 0ns || !object) {
490 qWarning(
"QEventDispatcherGlib::registerTimer: invalid arguments");
492 }
else if (object->thread() != thread() || thread() != QThread::currentThread()) {
493 qWarning(
"QEventDispatcherGlib::registerTimer: timers cannot be started from another thread");
498 Q_D(QEventDispatcherGlib);
499 d->timerSource->timerList.registerTimer(timerId, interval, timerType, object);
QEventDispatcherGlibPrivate * d