aboutsummaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2025-06-05 08:37:34 +0200
committerSebastiano Tronto <sebastiano@tronto.net>2025-06-05 08:37:34 +0200
commit52c74a1c33ce12b93ec5830f5a6348d9578c7c6e (patch)
treee763fa21a5bc057b36a42af8caa9766bb1cfd8b3 /web
parent57f194ef57e393d84e2d3c73115ec528e02ea3c9 (diff)
downloadnissy-core-52c74a1c33ce12b93ec5830f5a6348d9578c7c6e.tar.gz
nissy-core-52c74a1c33ce12b93ec5830f5a6348d9578c7c6e.zip
Simplify callback business (web version)
Diffstat (limited to '')
-rw-r--r--web/adapter.cpp27
-rw-r--r--web/callback.js52
-rwxr-xr-xweb/http/start-server.sh8
-rw-r--r--web/http/worker.mjs14
-rw-r--r--web/logging.h16
5 files changed, 39 insertions, 78 deletions
diff --git a/web/adapter.cpp b/web/adapter.cpp
index 0022b0d..3df3a54 100644
--- a/web/adapter.cpp
+++ b/web/adapter.cpp
@@ -1,15 +1,10 @@
1extern "C" {
2 extern int addCallbackFunction(/* args intentionally unspecified */);
3 extern void callFunction(int, const char *);
4 extern int callFunctionInt(int);
5}
6
7#include "../cpp/nissy.h" 1#include "../cpp/nissy.h"
8#include "storage.h" 2#include "storage.h"
9#include "logging.h" 3#include "logging.h"
10 4
11#include <emscripten.h> 5#include <emscripten.h>
12#include <emscripten/bind.h> 6#include <emscripten/bind.h>
7#include <functional>
13#include <map> 8#include <map>
14#include <set> 9#include <set>
15#include <string> 10#include <string>
@@ -17,6 +12,8 @@ extern "C" {
17 12
18EM_ASYNC_JS(void, fake_async, (), {}); 13EM_ASYNC_JS(void, fake_async, (), {});
19 14
15std::map<std::string, nissy::solver> loaded_solvers;
16
20const std::set<std::string> available_solvers 17const std::set<std::string> available_solvers
21{ 18{
22 "h48h0k4", 19 "h48h0k4",
@@ -27,8 +24,6 @@ const std::set<std::string> available_solvers
27 "h48h5k2", 24 "h48h5k2",
28}; 25};
29 26
30std::map<std::string, nissy::solver> loaded_solvers;
31
32bool is_solver_available(const std::string& name) 27bool is_solver_available(const std::string& name)
33{ 28{
34 return available_solvers.contains(name); 29 return available_solvers.contains(name);
@@ -153,16 +148,20 @@ bool init_solver_generate(const std::string& name)
153 148
154int poll_status(void *arg) 149int poll_status(void *arg)
155{ 150{
156 if (arg == NULL || *(int *)arg == -1) 151 if (arg == nullptr)
157 return nissy::status::RUN.value; 152 return nissy::status::RUN.value;
158 153
159 return callFunctionInt(*(int *)arg); 154 std::function<int(void)> poll((int (*)(void))arg);
155 return poll();
160} 156}
161 157
158// The parameter js_poll_status is of type int here, but actually it is a
159// pointer to a JS function. The type will have to be changed to a 64-bit
160// integer when we move to WASM64.
162nissy::solver::solve_result solve(std::string name, 161nissy::solver::solve_result solve(std::string name,
163 nissy::cube cube, nissy::nissflag nissflag, unsigned minmoves, 162 nissy::cube cube, nissy::nissflag nissflag, unsigned minmoves,
164 unsigned maxmoves, unsigned maxsols, unsigned optimal, unsigned threads, 163 unsigned maxmoves, unsigned maxsols, unsigned optimal, unsigned threads,
165 int poll_status_id) 164 int js_poll_status)
166{ 165{
167 // Here we use a dirty trick to make this function always return the 166 // Here we use a dirty trick to make this function always return the
168 // same kind of JavaScript object. If we did not do this, the returned 167 // same kind of JavaScript object. If we did not do this, the returned
@@ -178,8 +177,11 @@ nissy::solver::solve_result solve(std::string name,
178 {.err = nissy::error::INVALID_SOLVER}; 177 {.err = nissy::error::INVALID_SOLVER};
179 } 178 }
180 179
180 // TODO: when running multiple solvers at the same time, we could use
181 // poll_status_id as intended (i.e. an id of some sort)
181 return loaded_solvers.at(name).solve(cube, nissflag, minmoves, 182 return loaded_solvers.at(name).solve(cube, nissflag, minmoves,
182 maxmoves, maxsols, optimal, threads, poll_status, &poll_status_id); 183 maxmoves, maxsols, optimal, threads,
184 poll_status, &js_poll_status);
183} 185}
184 186
185EMSCRIPTEN_BINDINGS(Nissy) 187EMSCRIPTEN_BINDINGS(Nissy)
@@ -244,5 +246,4 @@ EMSCRIPTEN_BINDINGS(Nissy)
244 emscripten::return_value_policy::take_ownership()); 246 emscripten::return_value_policy::take_ownership());
245 emscripten::function("setLogger", &set_logger, 247 emscripten::function("setLogger", &set_logger,
246 emscripten::allow_raw_pointers()); 248 emscripten::allow_raw_pointers());
247 emscripten::function("addCallbackFunction", &addCallbackFunction);
248} 249}
diff --git a/web/callback.js b/web/callback.js
deleted file mode 100644
index e277cf5..0000000
--- a/web/callback.js
+++ /dev/null
@@ -1,52 +0,0 @@
1addToLibrary({
2
3cbfl: [],
4
5validateCallbackId__deps: [ 'cbfl' ],
6validateCallbackId: function(i) {
7 if (i < 0) {
8 console.log("--- WARNING ---");
9 console.log("Trying to access callback function of invalid id " + i);
10 console.log("--- WARNING ---");
11 return false;
12 }
13
14 if (i >= _cbfl.length) {
15 console.log("--- WARNING ---");
16 console.log("Trying to access callback function " + i + ", but only "
17 + _cbfl.length + " have been registered. This may be caused by a "
18 + "call outside of the main thread.");
19 console.log("--- WARNING ---");
20 return false;
21 }
22
23 return true;
24},
25
26addCallbackFunction__deps: [ 'cbfl' ],
27addCallbackFunction: function(f) {
28 _cbfl.push(f)
29 return _cbfl.length - 1
30},
31
32callFunction__deps: [ 'cbfl', 'validateCallbackId' ],
33callFunction: function(id, arg) {
34 // This is a workaround related to usign WASM64
35 // JavaScript's UTF8ToString expects a pointer argument, which for JS is
36 // of type "number", but WASM64 is passing a BigInt. See also:
37 // https://github.com/emscripten-core/emscripten/issues/21541
38 // (but I could not make the suggested solution work in this case).
39 // TODO: check if there is a better workaround.
40 const non64_arg = Number(arg);
41 if (_validateCallbackId(id))
42 _cbfl[id](UTF8ToString(non64_arg));
43},
44
45callFunctionInt__deps: [ 'cbfl', 'validateCallbackId' ],
46callFunctionInt: function(id) {
47 if (_validateCallbackId(id))
48 return _cbfl[id]();
49 return 0;
50},
51
52});
diff --git a/web/http/start-server.sh b/web/http/start-server.sh
new file mode 100755
index 0000000..c827146
--- /dev/null
+++ b/web/http/start-server.sh
@@ -0,0 +1,8 @@
1#!/bin/sh
2
3# Run this script from the main folder (../../)
4
5darkhttpd web/http \
6 --header 'Cross-Origin-Opener-Policy: same-origin' \
7 --header 'Cross-Origin-Embedder-Policy: require-corp' \
8 --mimetypes web/http/mime
diff --git a/web/http/worker.mjs b/web/http/worker.mjs
index d912e8b..0c1acb9 100644
--- a/web/http/worker.mjs
+++ b/web/http/worker.mjs
@@ -1,14 +1,16 @@
1import Nissy from "./nissy_web_module.mjs" 1import Nissy from "./nissy_web_module.mjs"
2 2
3const nissy = await Nissy(); 3const nissy = await Nissy();
4const log = (msg) => postMessage({ command: "log", id: -1, object: msg });
5nissy.setLogger(nissy._addCallbackFunction(log));
6 4
7var solveStatus = nissy.statusRUN; // For now this is a global variable 5const log = (cstr) => postMessage({
8const pollStatusCallback = nissy._addCallbackFunction(() => { 6 command: "log", id: -1,
9console.log("Calling pollstatus, returning " + solveStatus); 7 object: nissy.UTF8ToString(cstr)
10return solveStatus;
11}); 8});
9nissy.setLogger(nissy.addFunction(log, "vp"));
10
11var solveStatus = nissy.statusRUN; // For now this is a global variable
12const pollStatus = () => solveStatus;
13const pollStatusCallback = nissy.addFunction(pollStatus, "i");
12 14
13const commands = [ 15const commands = [
14 { name: "load solver data", exec: loadSolverDataFromStorage }, 16 { name: "load solver data", exec: loadSolverDataFromStorage },
diff --git a/web/logging.h b/web/logging.h
index 9ed4835..14609a0 100644
--- a/web/logging.h
+++ b/web/logging.h
@@ -1,11 +1,9 @@
1static int logger_id = -1; 1static void (*js_log)(const char *) = nullptr;
2 2
3void log(std::string s) 3void log(std::string s)
4{ 4{
5 if (logger_id == -1) 5 if (js_log != nullptr)
6 return; 6 js_log(s.c_str());
7
8 callFunction(logger_id, s.c_str());
9} 7}
10 8
11void log_wrapper(const char *cstr, void *data) 9void log_wrapper(const char *cstr, void *data)
@@ -13,8 +11,12 @@ void log_wrapper(const char *cstr, void *data)
13 log(cstr); 11 log(cstr);
14} 12}
15 13
16void set_logger(int id) 14/*
15To receive a function pointer for JS, we use an int parameter.
16This will have to be changed to a 64-bit integer when we move to WASM64.
17*/
18void set_logger(int f)
17{ 19{
18 logger_id = id; 20 js_log = (void (*)(const char *))f;
19 nissy::set_logger(log_wrapper, NULL); 21 nissy::set_logger(log_wrapper, NULL);
20} 22}

Generated with cgit - Back to sebastiano.tronto.net