wasm: use emscripten::ProxyingQueue

Use ProxyingQueue for proxing calls from secondary threads
to the main thread. This replaces the previous usage of the
private emscripten_async_run...() API.

Keep the existing "trampoline" which in addition proxies
using a JavaScript zero timer. This makes sure that
the proxied call is made with a clean stack, and not
e.g. while the main thread is waiting on a mutex.

Change-Id: I66cfdc2cf4bc733b1732973677c2ae46d85c8e7c
Reviewed-by: Mikołaj Boc <Mikolaj.Boc@qt.io>
This commit is contained in:
Morten Sørvig 2023-02-27 12:01:24 +01:00
parent 55568b8c62
commit 50057fec93
2 changed files with 15 additions and 2 deletions

View File

@ -116,6 +116,8 @@ Q_CONSTINIT QEventDispatcherWasm *QEventDispatcherWasm::g_mainThreadEventDispatc
#if QT_CONFIG(thread)
Q_CONSTINIT QVector<QEventDispatcherWasm *> QEventDispatcherWasm::g_secondaryThreadEventDispatchers;
Q_CONSTINIT std::mutex QEventDispatcherWasm::g_staticDataMutex;
emscripten::ProxyingQueue QEventDispatcherWasm::g_proxyingQueue;
pthread_t QEventDispatcherWasm::g_mainThread;
#endif
// ### dynamic initialization:
std::multimap<int, QSocketNotifier *> QEventDispatcherWasm::g_socketNotifiers;
@ -144,6 +146,9 @@ QEventDispatcherWasm::QEventDispatcherWasm()
// dispatchers so we set a global pointer to it.
Q_ASSERT(g_mainThreadEventDispatcher == nullptr);
g_mainThreadEventDispatcher = this;
#if QT_CONFIG(thread)
g_mainThread = pthread_self();
#endif
} else {
#if QT_CONFIG(thread)
std::lock_guard<std::mutex> lock(g_staticDataMutex);
@ -818,7 +823,9 @@ void QEventDispatcherWasm::runOnMainThread(std::function<void(void)> fn)
#if QT_CONFIG(thread)
if (!emscripten_is_main_runtime_thread()) {
void *context = new std::function<void(void)>(fn);
emscripten_async_run_in_main_runtime_thread_(EM_FUNC_SIG_VI, reinterpret_cast<void *>(trampoline), context);
g_proxyingQueue.proxyAsync(g_mainThread, [context]{
trampoline(context);
});
return;
}
#endif
@ -832,7 +839,9 @@ void QEventDispatcherWasm::runOnMainThreadAsync(std::function<void(void)> fn)
void *context = new std::function<void(void)>(fn);
#if QT_CONFIG(thread)
if (!emscripten_is_main_runtime_thread()) {
emscripten_async_run_in_main_runtime_thread_(EM_FUNC_SIG_VI, reinterpret_cast<void *>(trampoline), context);
g_proxyingQueue.proxyAsync(g_mainThread, [context]{
trampoline(context);
});
return;
}
#endif

View File

@ -24,6 +24,8 @@
#include <optional>
#include <tuple>
#include <emscripten/proxying.h>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher);
@ -106,6 +108,8 @@ private:
static QVector<QEventDispatcherWasm *> g_secondaryThreadEventDispatchers;
static std::mutex g_staticDataMutex;
static emscripten::ProxyingQueue g_proxyingQueue;
static pthread_t g_mainThread;
// Note on mutex usage: the global g_staticDataMutex protects the global (g_ prefixed) data,
// while the per eventdispatcher m_mutex protects the state accociated with blocking and waking