Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / ui / qt / glib_mainloop_on_qeventloop.cpp
blobc92901b5441944e036e3e5310ca61d529ad7e2d6
1 /** @file
3 * Copyright 2022 Tomasz Mon <desowin@gmail.com>
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
8 #include <glib.h>
10 #include <QTimer>
11 #include "glib_mainloop_on_qeventloop.h"
13 GLibPoller::GLibPoller(GMainContext *context) :
14 mutex_(), dispatched_(),
15 ctx_(context), priority_(0),
16 fds_(g_new(GPollFD, 1)), allocated_fds_(1), nfds_(0)
18 g_main_context_ref(ctx_);
21 GLibPoller::~GLibPoller()
23 g_main_context_unref(ctx_);
24 g_free(fds_);
27 void GLibPoller::run()
29 int timeout;
31 mutex_.lock();
32 while (!isInterruptionRequested())
34 while (!g_main_context_acquire(ctx_))
36 /* In normal circumstances context is acquired right away */
38 g_main_context_prepare(ctx_, &priority_);
39 while ((nfds_ = g_main_context_query(ctx_, priority_, &timeout, fds_,
40 allocated_fds_)) > allocated_fds_)
42 g_free(fds_);
43 fds_ = g_new(GPollFD, nfds_);
44 allocated_fds_ = nfds_;
46 /* Blocking g_poll() call is the reason for separate polling thread */
47 g_poll(fds_, nfds_, timeout);
48 g_main_context_release(ctx_);
50 /* Polling has finished, dispatch events (if any) in main thread so we
51 * don't have to worry about concurrency issues in GLib callbacks.
53 emit polled();
54 /* Wait for the main thread to finish dispatching before next poll */
55 dispatched_.wait(&mutex_);
57 mutex_.unlock();
60 GLibMainloopOnQEventLoop::GLibMainloopOnQEventLoop(QObject *parent) :
61 QObject(parent),
62 poller_(g_main_context_default())
64 connect(&poller_, &GLibPoller::polled,
65 this, &GLibMainloopOnQEventLoop::checkAndDispatch);
66 poller_.setObjectName("GLibPoller");
67 poller_.start();
70 GLibMainloopOnQEventLoop::~GLibMainloopOnQEventLoop()
72 poller_.requestInterruption();
73 /* Wakeup poller thread in case it is blocked on g_poll(). Wakeup does not
74 * cause any problem if poller thread is already waiting on dispatched wait
75 * condition.
77 g_main_context_wakeup(poller_.ctx_);
78 /* Wakeup poller thread without actually dispatching */
79 poller_.mutex_.lock();
80 poller_.dispatched_.wakeOne();
81 poller_.mutex_.unlock();
82 /* Poller thread will quit, wait for it to avoid warning */
83 poller_.wait();
86 void GLibMainloopOnQEventLoop::checkAndDispatch()
88 poller_.mutex_.lock();
89 while (!g_main_context_acquire(poller_.ctx_))
91 /* In normal circumstances context is acquired right away */
93 if (g_main_depth() > 0)
95 /* This should not happen, but if it does warn about nested event loops
96 * so the issue can be fixed before the harm is done. To identify root
97 * cause, put breakpoint here and take backtrace when it hits. Look for
98 * calls to exec() and processEvents() functions. Refactor the code so
99 * it does not spin additional event loops.
101 * Ignoring this warning will lead to very strange and hard to debug
102 * problems in the future.
104 qWarning("Nested GLib event loop detected");
106 if (g_main_context_check(poller_.ctx_, poller_.priority_,
107 poller_.fds_, poller_.nfds_))
109 g_main_context_dispatch(poller_.ctx_);
111 g_main_context_release(poller_.ctx_);
112 /* Start next iteration in GLibPoller thread */
113 poller_.dispatched_.wakeOne();
114 poller_.mutex_.unlock();
117 void GLibMainloopOnQEventLoop::setup(QObject *parent)
119 /* Schedule event loop action so we can check if Qt runs GLib mainloop */
120 QTimer::singleShot(0, [parent]() {
121 if (g_main_depth() == 0)
123 /* Not running inside GLib mainloop, actually setup */
124 new GLibMainloopOnQEventLoop(parent);