7#include <QtCore/qcoreapplication.h>
8#include <QtCore/qsocketnotifier.h>
10#include "emscripten.h"
14#define LOCK_GUARD(M) std::lock_guard<std::mutex> lock(M)
20Q_CONSTINIT std::mutex QWasmSocket::g_socketDataMutex;
24std::multimap<
int, QSocketNotifier *>
QWasmSocket::g_socketNotifiers;
25std::map<
int, QWasmSocket::SocketReadyState>
QWasmSocket::g_socketState;
27void QWasmSocket::registerSocketNotifier(QSocketNotifier *notifier)
31 bool wasEmpty = g_socketNotifiers.empty();
32 g_socketNotifiers.insert({notifier->socket(), notifier});
37 ioctl(notifier->socket(), FIONREAD, &count);
40 if (count > 0 && notifier->type() == QSocketNotifier::Read) {
41 QCoreApplication::postEvent(notifier,
new QEvent(QEvent::SockAct));
45void QWasmSocket::unregisterSocketNotifier(QSocketNotifier *notifier)
49 auto notifiers = g_socketNotifiers.equal_range(notifier->socket());
50 for (
auto it = notifiers.first; it != notifiers.second; ++it) {
51 if (it->second == notifier) {
52 g_socketNotifiers.erase(it);
57 if (g_socketNotifiers.empty())
64 if (!g_socketNotifiers.empty()) {
65 qWarning(
"QWasmSocket: Sockets cleared with active socket notifiers");
67 g_socketNotifiers.clear();
69 g_socketState.clear();
74 qCDebug(lcEventDispatcher) <<
"setEmscriptenSocketCallbacks";
86 qCDebug(lcEventDispatcher) <<
"clearEmscriptenSocketCallbacks";
88 emscripten_set_socket_error_callback(
nullptr,
nullptr);
89 emscripten_set_socket_open_callback(
nullptr,
nullptr);
90 emscripten_set_socket_listen_callback(
nullptr,
nullptr);
91 emscripten_set_socket_connection_callback(
nullptr,
nullptr);
92 emscripten_set_socket_message_callback(
nullptr,
nullptr);
93 emscripten_set_socket_close_callback(
nullptr,
nullptr);
111 auto notifiersRange = g_socketNotifiers.equal_range(socket);
112 std::vector<std::pair<
int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
113 for (
auto [_, notifier]: notifiers) {
114 QCoreApplication::postEvent(notifier,
new QEvent(QEvent::SockAct));
125 auto notifiersRange = g_socketNotifiers.equal_range(socket);
126 std::vector<std::pair<
int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
127 for (
auto [_, notifier]: notifiers) {
128 if (notifier->type() == QSocketNotifier::Write) {
129 QCoreApplication::postEvent(notifier,
new QEvent(QEvent::SockAct));
153 auto notifiersRange = g_socketNotifiers.equal_range(socket);
154 std::vector<std::pair<
int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
155 for (
auto [_, notifier]: notifiers) {
156 if (notifier->type() == QSocketNotifier::Read) {
157 QCoreApplication::postEvent(notifier,
new QEvent(QEvent::SockAct));
174 auto notifiersRange = g_socketNotifiers.equal_range(socket);
175 std::vector<std::pair<
int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
176 for (
auto [_, notifier]: notifiers)
177 QCoreApplication::postEvent(notifier,
new QEvent(QEvent::SockClose));
187 SocketReadyState &state = g_socketState[socket];
191 state.readyRead |= setReadyRead;
192 state.readyWrite |= setReadyWrite;
196 if (QEventDispatcherWasm *waiter = state.waiter)
197 if ((state.readyRead && state.waitForReadyRead) || (state.readyWrite && state.waitForReadyWrite))
204 g_socketState.erase(socket);
207void QWasmSocket::waitForSocketState(QEventDispatcherWasm *eventDispatcher,
int timeout,
int socket,
bool checkRead,
208 bool checkWrite,
bool *selectForRead,
bool *selectForWrite,
bool *socketDisconnect)
213 *selectForRead =
false;
214 *selectForWrite =
false;
221 SocketReadyState &state = g_socketState[socket];
223 qWarning() <<
"QEventDispatcherWasm::waitForSocketState: a thread is already waiting";
227 bool shouldWait =
true;
228 if (checkRead && state.readyRead) {
230 state.readyRead =
false;
231 *selectForRead =
true;
233 if (checkWrite && state.readyWrite) {
235 state.readyWrite =
false;
236 *selectForRead =
true;
241 state.waiter = eventDispatcher;
242 state.waitForReadyRead = checkRead;
243 state.waitForReadyWrite = checkWrite;
246 bool didTimeOut = !eventDispatcher->wait(timeout);
251 auto it = g_socketState.find(socket);
252 if (it == g_socketState.end()) {
253 *socketDisconnect =
true;
256 it->second.waiter =
nullptr;
257 it->second.waitForReadyRead =
false;
258 it->second.waitForReadyWrite =
false;
static void setSocketState(int socket, bool setReadyRead, bool setReadyWrite)
static void setEmscriptenSocketCallbacks()
static void socketConnection(int fd, void *context)
static void socketClose(int fd, void *context)
static void clearSocketState(int socket)
static void clearEmscriptenSocketCallbacks()
static void socketListen(int fd, void *context)
static void socketOpen(int fd, void *context)
static void clearSocketNotifiers()
static void socketError(int fd, int err, const char *msg, void *context)
static void socketMessage(int fd, void *context)
void runAsync(std::function< void(void)> fn)
void runOnMainThread(std::function< void(void)> fn)