summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMorten Sørvig <[email protected]>2024-12-19 15:05:56 +0100
committerMorten Sørvig <[email protected]>2025-03-03 18:24:43 +0100
commit9df167a013b6db0957e35d3924e331a145d518b2 (patch)
tree20b01ca440c181078f5f19baab2df5e0654fed74 /src
parentb80deb26280ad693cd24fe5e723b385bf9ffa15b (diff)
wasm: introduce qwasmglobal_p.h
Global helpers/utils for Q_OS_WASM. Move the thread proxying functions to qwasmglobal_p.h, and update calling code. qtstweb_p.h now contains C++ wrappers for native web API only. The proxying functions will be removed from qeventdispatcher_wasm in a later commit. Change-Id: I08a56c211b08929750970895b63ca48d4a07a0a1 Reviewed-by: Lorn Potter <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/CMakeLists.txt1
-rw-r--r--src/corelib/io/qsettings_wasm.cpp13
-rw-r--r--src/corelib/platform/wasm/qstdweb.cpp2
-rw-r--r--src/corelib/platform/wasm/qstdweb_p.h42
-rw-r--r--src/corelib/platform/wasm/qwasmglobal.cpp56
-rw-r--r--src/corelib/platform/wasm/qwasmglobal_p.h69
-rw-r--r--src/corelib/platform/wasm/qwasmsocket.cpp13
-rw-r--r--src/network/access/qnetworkreplywasmimpl.cpp4
8 files changed, 144 insertions, 56 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 8d0e60af9b9..68745591d2c 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -1440,6 +1440,7 @@ endif()
qt_internal_extend_target(Core CONDITION WASM
SOURCES
+ platform/wasm/qwasmglobal.cpp platform/wasm/qwasmglobal_p.h
platform/wasm/qstdweb.cpp platform/wasm/qstdweb_p.h
platform/wasm/qwasmsocket.cpp platform/wasm/qwasmsocket_p.h
platform/wasm/qwasmsuspendresumecontrol.cpp platform/wasm/qwasmsuspendresumecontrol_p.h
diff --git a/src/corelib/io/qsettings_wasm.cpp b/src/corelib/io/qsettings_wasm.cpp
index 7d80ff82d37..72045a2d519 100644
--- a/src/corelib/io/qsettings_wasm.cpp
+++ b/src/corelib/io/qsettings_wasm.cpp
@@ -11,6 +11,7 @@
#endif // QT_NO_QOBJECT
#include <QDebug>
#include <QtCore/private/qstdweb_p.h>
+#include <QtCore/private/qwasmglobal_p.h>
#include <QFileInfo>
#include <QDir>
@@ -109,7 +110,7 @@ void QWasmLocalStorageSettingsPrivate::remove(const QString &key)
{
const std::string removed = QString(m_keyPrefixes.first() + key).toStdString();
- qstdweb::runTaskOnMainThread<void>([this, &removed, &key]() {
+ qwasmglobal::runTaskOnMainThread<void>([this, &removed, &key]() {
std::vector<std::string> children = { removed };
const int length = val::global("window")["localStorage"]["length"].as<int>();
for (int i = 0; i < length; ++i) {
@@ -131,7 +132,7 @@ void QWasmLocalStorageSettingsPrivate::remove(const QString &key)
void QWasmLocalStorageSettingsPrivate::set(const QString &key, const QVariant &value)
{
- qstdweb::runTaskOnMainThread<void>([this, &key, &value]() {
+ qwasmglobal::runTaskOnMainThread<void>([this, &key, &value]() {
const std::string keyString = QString(m_keyPrefixes.first() + key).toStdString();
const std::string valueString = QSettingsPrivate::variantToString(value).toStdString();
val::global("window")["localStorage"].call<void>("setItem", keyString, valueString);
@@ -140,7 +141,7 @@ void QWasmLocalStorageSettingsPrivate::set(const QString &key, const QVariant &v
std::optional<QVariant> QWasmLocalStorageSettingsPrivate::get(const QString &key) const
{
- return qstdweb::runTaskOnMainThread<std::optional<QVariant>>(
+ return qwasmglobal::runTaskOnMainThread<std::optional<QVariant>>(
[this, &key]() -> std::optional<QVariant> {
for (const auto &prefix : m_keyPrefixes) {
const std::string keyString = QString(prefix + key).toStdString();
@@ -160,7 +161,7 @@ std::optional<QVariant> QWasmLocalStorageSettingsPrivate::get(const QString &key
QStringList QWasmLocalStorageSettingsPrivate::children(const QString &prefix, ChildSpec spec) const
{
- return qstdweb::runTaskOnMainThread<QStringList>([this, &prefix, &spec]() -> QStringList {
+ return qwasmglobal::runTaskOnMainThread<QStringList>([this, &prefix, &spec]() -> QStringList {
QSet<QString> nodes;
// Loop through all keys on window.localStorage, return Qt keys belonging to
// this application, with the correct prefix, and according to ChildSpec.
@@ -192,7 +193,7 @@ QStringList QWasmLocalStorageSettingsPrivate::children(const QString &prefix, Ch
void QWasmLocalStorageSettingsPrivate::clear()
{
- qstdweb::runTaskOnMainThread<void>([this]() {
+ qwasmglobal::runTaskOnMainThread<void>([this]() {
// Get all Qt keys from window.localStorage
const int length = val::global("window")["localStorage"]["length"].as<int>();
QStringList keys;
@@ -347,7 +348,7 @@ QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::
// Check if cookies are enabled (required for using persistent storage)
- const bool cookiesEnabled = qstdweb::runTaskOnMainThread<bool>(
+ const bool cookiesEnabled = qwasmglobal::runTaskOnMainThread<bool>(
[]() { return val::global("navigator")["cookieEnabled"].as<bool>(); });
constexpr QLatin1StringView cookiesWarningMessage(
diff --git a/src/corelib/platform/wasm/qstdweb.cpp b/src/corelib/platform/wasm/qstdweb.cpp
index c51c7e827c2..970e717212d 100644
--- a/src/corelib/platform/wasm/qstdweb.cpp
+++ b/src/corelib/platform/wasm/qstdweb.cpp
@@ -2,6 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstdweb_p.h"
+#include "qwasmsuspendresumecontrol_p.h"
+#include "qwasmglobal_p.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qfile.h>
diff --git a/src/corelib/platform/wasm/qstdweb_p.h b/src/corelib/platform/wasm/qstdweb_p.h
index 5cb5db1f549..d34b86bce73 100644
--- a/src/corelib/platform/wasm/qstdweb_p.h
+++ b/src/corelib/platform/wasm/qstdweb_p.h
@@ -290,48 +290,6 @@ namespace qstdweb {
bool Q_CORE_EXPORT haveAsyncify();
bool Q_CORE_EXPORT haveJspi();
bool canBlockCallingThread();
-
- struct CancellationFlag
- {
- };
-
-#if QT_CONFIG(thread)
- template<class T>
- T proxyCall(std::function<T()> task, emscripten::ProxyingQueue *queue)
- {
- T result;
- queue->proxySync(emscripten_main_runtime_thread_id(),
- [task, result = &result]() { *result = task(); });
- return result;
- }
-
- template<>
- inline void proxyCall<void>(std::function<void()> task, emscripten::ProxyingQueue *queue)
- {
- queue->proxySync(emscripten_main_runtime_thread_id(), task);
- }
-
- template<class T>
- T runTaskOnMainThread(std::function<T()> task, emscripten::ProxyingQueue *queue)
- {
- return emscripten_is_main_runtime_thread() ? task() : proxyCall<T>(std::move(task), queue);
- }
-
- template<class T>
- T runTaskOnMainThread(std::function<T()> task)
- {
- emscripten::ProxyingQueue singleUseQueue;
- return runTaskOnMainThread<T>(task, &singleUseQueue);
- }
-
-#else
- template<class T>
- T runTaskOnMainThread(std::function<T()> task)
- {
- return task();
- }
-#endif // QT_CONFIG(thread)
-
}
QT_END_NAMESPACE
diff --git a/src/corelib/platform/wasm/qwasmglobal.cpp b/src/corelib/platform/wasm/qwasmglobal.cpp
new file mode 100644
index 00000000000..f80db160f08
--- /dev/null
+++ b/src/corelib/platform/wasm/qwasmglobal.cpp
@@ -0,0 +1,56 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwasmglobal_p.h"
+
+namespace qwasmglobal {
+
+Q_GLOBAL_STATIC(emscripten::ProxyingQueue, proxyingQueue);
+
+namespace {
+ void trampoline(void *context) {
+
+ auto async_fn = [](void *context){
+ std::function<void(void)> *fn = reinterpret_cast<std::function<void(void)> *>(context);
+ (*fn)();
+ delete fn;
+ };
+
+ emscripten_async_call(async_fn, context, 0);
+ }
+}
+
+void runOnMainThread(std::function<void(void)> fn)
+{
+#if QT_CONFIG(thread)
+ runTaskOnMainThread<void>(fn, proxyingQueue());
+#else
+ runTaskOnMainThread<void>(fn);
+#endif
+}
+
+// Runs a function asynchronously. Main thread only.
+void runAsync(std::function<void(void)> fn)
+{
+ Q_ASSERT(emscripten_is_main_runtime_thread());
+ trampoline(new std::function<void(void)>(fn));
+}
+
+// Runs a function on the main thread. The function always runs asynchronously,
+// also if the calling thread is the main thread.
+void runOnMainThreadAsync(std::function<void(void)> fn)
+{
+ void *context = new std::function<void(void)>(fn);
+#if QT_CONFIG(thread)
+ if (!emscripten_is_main_runtime_thread()) {
+ proxyingQueue()->proxyAsync(emscripten_main_runtime_thread_id(), [context]{
+ trampoline(context);
+ });
+ return;
+ }
+#endif
+ trampoline(context);
+}
+
+}
+
diff --git a/src/corelib/platform/wasm/qwasmglobal_p.h b/src/corelib/platform/wasm/qwasmglobal_p.h
new file mode 100644
index 00000000000..3d80014268d
--- /dev/null
+++ b/src/corelib/platform/wasm/qwasmglobal_p.h
@@ -0,0 +1,69 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWASMGLOBAL_P_H
+#define QWASMGLOBAL_P_H
+
+#include <emscripten/proxying.h>
+#include <emscripten/threading.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+namespace qwasmglobal {
+
+#if QT_CONFIG(thread)
+ template<class T>
+ T proxyCall(std::function<T()> task, emscripten::ProxyingQueue *queue)
+ {
+ T result;
+ queue->proxySync(emscripten_main_runtime_thread_id(),
+ [task, result = &result]() { *result = task(); });
+ return result;
+ }
+
+ template<>
+ inline void proxyCall<void>(std::function<void()> task, emscripten::ProxyingQueue *queue)
+ {
+ queue->proxySync(emscripten_main_runtime_thread_id(), task);
+ }
+
+ template<class T>
+ T runTaskOnMainThread(std::function<T()> task, emscripten::ProxyingQueue *queue)
+ {
+ return emscripten_is_main_runtime_thread() ? task() : proxyCall<T>(std::move(task), queue);
+ }
+
+ template<class T>
+ T runTaskOnMainThread(std::function<T()> task)
+ {
+ emscripten::ProxyingQueue singleUseQueue;
+ return runTaskOnMainThread<T>(task, &singleUseQueue);
+ }
+
+#else
+ template<class T>
+ T runTaskOnMainThread(std::function<T()> task)
+ {
+ return task();
+ }
+#endif // QT_CONFIG(thread)
+
+ void runAsync(std::function<void(void)> fn);
+ void runOnMainThread(std::function<void(void)> fn);
+ void runOnMainThreadAsync(std::function<void(void)> fn);
+}
+
+QT_END_NAMESPACE
+
+#endif // QWASMGLOBAL_P_H
diff --git a/src/corelib/platform/wasm/qwasmsocket.cpp b/src/corelib/platform/wasm/qwasmsocket.cpp
index e7901a54fb9..64af09e9871 100644
--- a/src/corelib/platform/wasm/qwasmsocket.cpp
+++ b/src/corelib/platform/wasm/qwasmsocket.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwasmsocket_p.h"
+#include "qwasmglobal_p.h"
#include <QtCore/qsocketnotifier.h>
#include "emscripten.h"
@@ -28,7 +29,7 @@ void QWasmSocket::registerSocketNotifier(QSocketNotifier *notifier)
bool wasEmpty = g_socketNotifiers.empty();
g_socketNotifiers.insert({notifier->socket(), notifier});
if (wasEmpty)
- QEventDispatcherWasm::runOnMainThread([] { setEmscriptenSocketCallbacks(); });
+ qwasmglobal::runOnMainThread([] { setEmscriptenSocketCallbacks(); });
int count;
ioctl(notifier->socket(), FIONREAD, &count);
@@ -52,7 +53,7 @@ void QWasmSocket::unregisterSocketNotifier(QSocketNotifier *notifier)
}
if (g_socketNotifiers.empty())
- QEventDispatcherWasm::runOnMainThread([] { clearEmscriptenSocketCallbacks(); });
+ qwasmglobal::runOnMainThread([] { clearEmscriptenSocketCallbacks(); });
}
void QWasmSocket::clearSocketNotifiers()
@@ -104,7 +105,7 @@ void QWasmSocket::socketError(int socket, int err, const char* msg, void *contex
// the Qt handler.
// It is currently unclear if this problem is caused by code in Qt or in Emscripten, or
// if this completely fixes the problem.
- QEventDispatcherWasm::runAsync([socket](){
+ qwasmglobal::runAsync([socket](){
auto notifiersRange = g_socketNotifiers.equal_range(socket);
std::vector<std::pair<int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
for (auto [_, notifier]: notifiers) {
@@ -118,7 +119,7 @@ void QWasmSocket::socketOpen(int socket, void *context)
{
Q_UNUSED(context);
- QEventDispatcherWasm::runAsync([socket](){
+ qwasmglobal::runAsync([socket](){
auto notifiersRange = g_socketNotifiers.equal_range(socket);
std::vector<std::pair<int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
for (auto [_, notifier]: notifiers) {
@@ -146,7 +147,7 @@ void QWasmSocket::socketMessage(int socket, void *context)
{
Q_UNUSED(context);
- QEventDispatcherWasm::runAsync([socket](){
+ qwasmglobal::runAsync([socket](){
auto notifiersRange = g_socketNotifiers.equal_range(socket);
std::vector<std::pair<int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
for (auto [_, notifier]: notifiers) {
@@ -167,7 +168,7 @@ void QWasmSocket::socketClose(int socket, void *context)
if (socket == 0)
return;
- QEventDispatcherWasm::runAsync([socket](){
+ qwasmglobal::runAsync([socket](){
auto notifiersRange = g_socketNotifiers.equal_range(socket);
std::vector<std::pair<int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
for (auto [_, notifier]: notifiers)
diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp
index 7d225c7e862..1bcf32e643a 100644
--- a/src/network/access/qnetworkreplywasmimpl.cpp
+++ b/src/network/access/qnetworkreplywasmimpl.cpp
@@ -9,7 +9,7 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qthread.h>
-#include <QtCore/private/qeventdispatcher_wasm_p.h>
+#include <QtCore/private/qwasmglobal_p.h>
#include <QtCore/private/qoffsetstringarray_p.h>
#include <QtCore/private/qtools_p.h>
@@ -281,7 +281,7 @@ void QNetworkReplyWasmImplPrivate::doSendRequest()
}
}
- QEventDispatcherWasm::runOnMainThread([attr, fetchContext = m_fetchContext]() mutable {
+ qwasmglobal::runOnMainThread([attr, fetchContext = m_fetchContext]() mutable {
std::unique_lock lock{ fetchContext->mutex };
if (fetchContext->state == FetchContext::State::CANCELED) {
fetchContext->state = FetchContext::State::FINISHED;