8#include <QtCore/qcoreapplication.h>
9#include <QtCore/qsocketnotifier.h>
11#include "emscripten.h"
15#define LOCK_GUARD(M) std::lock_guard<std::mutex> lock(M)
21Q_CONSTINIT std::mutex QWasmSocket::g_socketDataMutex;
25std::multimap<
int, QSocketNotifier *>
QWasmSocket::g_socketNotifiers;
26std::map<
int, QWasmSocket::SocketReadyState>
QWasmSocket::g_socketState;
28void QWasmSocket::registerSocketNotifier(QSocketNotifier *notifier)
32 bool wasEmpty = g_socketNotifiers.empty();
33 g_socketNotifiers.insert({notifier->socket(), notifier});
38 ioctl(notifier->socket(), FIONREAD, &count);
41 if (count > 0 && notifier->type() == QSocketNotifier::Read) {
42 QCoreApplication::postEvent(notifier,
new QEvent(QEvent::SockAct));
46void QWasmSocket::unregisterSocketNotifier(QSocketNotifier *notifier)
50 auto notifiers = g_socketNotifiers.equal_range(notifier->socket());
51 for (
auto it = notifiers.first; it != notifiers.second; ++it) {
52 if (it->second == notifier) {
53 g_socketNotifiers.erase(it);
58 if (g_socketNotifiers.empty())
65 if (!g_socketNotifiers.empty()) {
66 qWarning(
"QWasmSocket: Sockets cleared with active socket notifiers");
68 g_socketNotifiers.clear();
70 g_socketState.clear();
75 qCDebug(lcEventDispatcher) <<
"setEmscriptenSocketCallbacks";
87 qCDebug(lcEventDispatcher) <<
"clearEmscriptenSocketCallbacks";
89 emscripten_set_socket_error_callback(
nullptr,
nullptr);
90 emscripten_set_socket_open_callback(
nullptr,
nullptr);
91 emscripten_set_socket_listen_callback(
nullptr,
nullptr);
92 emscripten_set_socket_connection_callback(
nullptr,
nullptr);
93 emscripten_set_socket_message_callback(
nullptr,
nullptr);
94 emscripten_set_socket_close_callback(
nullptr,
nullptr);
112 auto notifiersRange = g_socketNotifiers.equal_range(socket);
113 std::vector<std::pair<
int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
114 for (
auto [_, notifier]: notifiers) {
115 QCoreApplication::postEvent(notifier,
new QEvent(QEvent::SockAct));
126 auto notifiersRange = g_socketNotifiers.equal_range(socket);
127 std::vector<std::pair<
int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
128 for (
auto [_, notifier]: notifiers) {
129 if (notifier->type() == QSocketNotifier::Write) {
130 QCoreApplication::postEvent(notifier,
new QEvent(QEvent::SockAct));
154 auto notifiersRange = g_socketNotifiers.equal_range(socket);
155 std::vector<std::pair<
int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
156 for (
auto [_, notifier]: notifiers) {
157 if (notifier->type() == QSocketNotifier::Read) {
158 QCoreApplication::postEvent(notifier,
new QEvent(QEvent::SockAct));
175 auto notifiersRange = g_socketNotifiers.equal_range(socket);
176 std::vector<std::pair<
int, QSocketNotifier *>> notifiers(notifiersRange.first, notifiersRange.second);
177 for (
auto [_, notifier]: notifiers)
178 QCoreApplication::postEvent(notifier,
new QEvent(QEvent::SockClose));
188 SocketReadyState &state = g_socketState[socket];
192 state.readyRead |= setReadyRead;
193 state.readyWrite |= setReadyWrite;
197 if (QEventDispatcherWasm *waiter = state.waiter)
198 if ((state.readyRead && state.waitForReadyRead) || (state.readyWrite && state.waitForReadyWrite))
205 g_socketState.erase(socket);
208void QWasmSocket::waitForSocketState(QEventDispatcherWasm *eventDispatcher,
int timeout,
int socket,
bool checkRead,
209 bool checkWrite,
bool *selectForRead,
bool *selectForWrite,
bool *socketDisconnect)
214 *selectForRead =
false;
215 *selectForWrite =
false;
222 SocketReadyState &state = g_socketState[socket];
224 qWarning() <<
"QEventDispatcherWasm::waitForSocketState: a thread is already waiting";
228 bool shouldWait =
true;
229 if (checkRead && state.readyRead) {
231 state.readyRead =
false;
232 *selectForRead =
true;
234 if (checkWrite && state.readyWrite) {
236 state.readyWrite =
false;
237 *selectForRead =
true;
242 state.waiter = eventDispatcher;
243 state.waitForReadyRead = checkRead;
244 state.waitForReadyWrite = checkWrite;
247 bool didTimeOut = !eventDispatcher->wait(timeout);
252 auto it = g_socketState.find(socket);
253 if (it == g_socketState.end()) {
254 *socketDisconnect =
true;
257 it->second.waiter =
nullptr;
258 it->second.waitForReadyRead =
false;
259 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)