Move runTaskOnMainThread to qstdweb_p.h, use it in WASM dispatcher
This unifies the approach to running sync tasks (possibly with a return value) on the main thread. Change-Id: I2a05c4f40115a79dbf03c03fa8d8db34124884dc Reviewed-by: Mikołaj Boc <Mikolaj.Boc@qt.io>
This commit is contained in:
parent
62caae9578
commit
141f0ca338
@ -16,6 +16,12 @@
|
|||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
#if QT_CONFIG(thread)
|
||||||
|
#define PROXYING_QUEUE_PARAM , &g_proxyingQueue
|
||||||
|
#else
|
||||||
|
#define PROXYING_QUEUE_PARAM
|
||||||
|
#endif // QT_CONFIG(thread)
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
// using namespace emscripten;
|
// using namespace emscripten;
|
||||||
@ -315,8 +321,10 @@ void QEventDispatcherWasm::registerSocketNotifier(QSocketNotifier *notifier)
|
|||||||
|
|
||||||
bool wasEmpty = g_socketNotifiers.empty();
|
bool wasEmpty = g_socketNotifiers.empty();
|
||||||
g_socketNotifiers.insert({notifier->socket(), notifier});
|
g_socketNotifiers.insert({notifier->socket(), notifier});
|
||||||
if (wasEmpty)
|
if (wasEmpty) {
|
||||||
runOnMainThread([]{ setEmscriptenSocketCallbacks(); });
|
qstdweb::runTaskOnMainThread<void>([] { setEmscriptenSocketCallbacks(); }
|
||||||
|
PROXYING_QUEUE_PARAM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEventDispatcherWasm::unregisterSocketNotifier(QSocketNotifier *notifier)
|
void QEventDispatcherWasm::unregisterSocketNotifier(QSocketNotifier *notifier)
|
||||||
@ -331,8 +339,10 @@ void QEventDispatcherWasm::unregisterSocketNotifier(QSocketNotifier *notifier)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_socketNotifiers.empty())
|
if (g_socketNotifiers.empty()) {
|
||||||
runOnMainThread([]{ clearEmscriptenSocketCallbacks(); });
|
qstdweb::runTaskOnMainThread<void>([] { clearEmscriptenSocketCallbacks(); }
|
||||||
|
PROXYING_QUEUE_PARAM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEventDispatcherWasm::registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object)
|
void QEventDispatcherWasm::registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object)
|
||||||
@ -528,14 +538,16 @@ bool QEventDispatcherWasm::wakeEventDispatcherThread()
|
|||||||
if (useJspi()) {
|
if (useJspi()) {
|
||||||
if (!qt_jspi_can_resume_js())
|
if (!qt_jspi_can_resume_js())
|
||||||
return false;
|
return false;
|
||||||
runOnMainThread([]{ qt_jspi_resume_js(); });
|
return qstdweb::runTaskOnMainThread<bool>([]() { return qt_jspi_resume_js(); }
|
||||||
return true;
|
PROXYING_QUEUE_PARAM);
|
||||||
}
|
}
|
||||||
if (g_is_asyncify_suspended) {
|
return g_is_asyncify_suspended
|
||||||
runOnMainThread([]{ qt_asyncify_resume(); });
|
&& qstdweb::runTaskOnMainThread<bool>(
|
||||||
return true;
|
[] {
|
||||||
}
|
qt_asyncify_resume();
|
||||||
return false;
|
return true;
|
||||||
|
}
|
||||||
|
PROXYING_QUEUE_PARAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process event activation callbacks for the main thread event dispatcher.
|
// Process event activation callbacks for the main thread event dispatcher.
|
||||||
@ -620,17 +632,19 @@ void QEventDispatcherWasm::updateNativeTimer()
|
|||||||
|
|
||||||
// Update the native timer for this thread/dispatcher. This must be
|
// Update the native timer for this thread/dispatcher. This must be
|
||||||
// done on the main thread where we have access to native API.
|
// done on the main thread where we have access to native API.
|
||||||
runOnMainThread([this, maintainNativeTimer]() {
|
qstdweb::runTaskOnMainThread<void>(
|
||||||
Q_ASSERT(emscripten_is_main_runtime_thread());
|
[this, maintainNativeTimer]() {
|
||||||
|
Q_ASSERT(emscripten_is_main_runtime_thread());
|
||||||
|
|
||||||
// "this" may have been deleted, or may be about to be deleted.
|
// "this" may have been deleted, or may be about to be deleted.
|
||||||
// Check if the pointer we have is still a valid event dispatcher,
|
// Check if the pointer we have is still a valid event dispatcher,
|
||||||
// and keep the mutex locked while updating the native timer to
|
// and keep the mutex locked while updating the native timer to
|
||||||
// prevent it from being deleted.
|
// prevent it from being deleted.
|
||||||
LOCK_GUARD(g_staticDataMutex);
|
LOCK_GUARD(g_staticDataMutex);
|
||||||
if (isValidEventDispatcherPointer(this))
|
if (isValidEventDispatcherPointer(this))
|
||||||
maintainNativeTimer();
|
maintainNativeTimer();
|
||||||
});
|
}
|
||||||
|
PROXYING_QUEUE_PARAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static timer activation callback. Must be called on the main thread
|
// Static timer activation callback. Must be called on the main thread
|
||||||
@ -896,22 +910,6 @@ void QEventDispatcherWasm::runAsync(std::function<void(void)> fn)
|
|||||||
trampoline(new std::function<void(void)>(fn));
|
trampoline(new std::function<void(void)>(fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Runs a function on the main thread. The function runs synchronusly if
|
|
||||||
// the calling thread is then main thread.
|
|
||||||
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);
|
|
||||||
g_proxyingQueue.proxyAsync(g_mainThread, [context]{
|
|
||||||
trampoline(context);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Runs a function on the main thread. The function always runs asynchronously,
|
// Runs a function on the main thread. The function always runs asynchronously,
|
||||||
// also if the calling thread is the main thread.
|
// also if the calling thread is the main thread.
|
||||||
void QEventDispatcherWasm::runOnMainThreadAsync(std::function<void(void)> fn)
|
void QEventDispatcherWasm::runOnMainThreadAsync(std::function<void(void)> fn)
|
||||||
|
@ -89,7 +89,6 @@ private:
|
|||||||
|
|
||||||
static void run(std::function<void(void)> fn);
|
static void run(std::function<void(void)> fn);
|
||||||
static void runAsync(std::function<void(void)> fn);
|
static void runAsync(std::function<void(void)> fn);
|
||||||
static void runOnMainThread(std::function<void(void)> fn);
|
|
||||||
static void runOnMainThreadAsync(std::function<void(void)> fn);
|
static void runOnMainThreadAsync(std::function<void(void)> fn);
|
||||||
|
|
||||||
static QEventDispatcherWasm *g_mainThreadEventDispatcher;
|
static QEventDispatcherWasm *g_mainThreadEventDispatcher;
|
||||||
|
@ -28,6 +28,11 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#if QT_CONFIG(thread)
|
||||||
|
#include <emscripten/proxying.h>
|
||||||
|
#include <emscripten/threading.h>
|
||||||
|
#endif // #if QT_CONFIG(thread)
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QMimeData;
|
class QMimeData;
|
||||||
@ -218,6 +223,43 @@ namespace qstdweb {
|
|||||||
Q_CORE_EXPORT std::shared_ptr<CancellationFlag>
|
Q_CORE_EXPORT std::shared_ptr<CancellationFlag>
|
||||||
readDataTransfer(emscripten::val webObject, std::function<QVariant(QByteArray)> imageReader,
|
readDataTransfer(emscripten::val webObject, std::function<QVariant(QByteArray)> imageReader,
|
||||||
std::function<void(std::unique_ptr<QMimeData>)> onDone);
|
std::function<void(std::unique_ptr<QMimeData>)> onDone);
|
||||||
|
|
||||||
|
#if QT_CONFIG(thread)
|
||||||
|
template<class T>
|
||||||
|
T proxyCall(std::function<T()> task, emscripten::ProxyingQueue *queue)
|
||||||
|
{
|
||||||
|
T result;
|
||||||
|
queue->proxySync(emscripten_main_browser_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_browser_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
|
QT_END_NAMESPACE
|
||||||
|
Loading…
Reference in New Issue
Block a user