Rework fallback for postMessage issue

Now initialise all workers with module+memory separately, and then instead of using postMessage to send thread pointers, push them into a crossbeam-deque on the Rust side.

Rayon already depends on crossbeam-dequeue, so we're not even adding another dependency, and this model allows us to push "tasks" (thread pointers) on the main thread and pop them on worker threads in arbitrary order without sacrificing correctness.
This commit is contained in:
Ingvar Stepanyan
2020-04-27 23:18:42 +01:00
committed by Ingvar Stepanyan
parent 4c658b79ef
commit 0747d2c419
12 changed files with 253 additions and 255 deletions

View File

@@ -1,42 +1,44 @@
mod malloc_shim;
use js_sys::Array;
use crossbeam_deque::Injector;
use once_cell::sync::OnceCell;
use wasm_bindgen::prelude::*;
use wasm_bindgen::{JsCast, JsValue};
use wasm_bindgen::JsValue;
use oxipng::AlphaOptim;
#[wasm_bindgen]
extern "C" {
type Worker;
#[wasm_bindgen(js_namespace = Array, js_name = of)]
fn array_of_2(a: JsValue, b: JsValue) -> JsValue;
}
#[wasm_bindgen(method, js_name = postMessage)]
fn post_message(worker: &Worker, msg: JsValue);
static TASKS: OnceCell<Injector<rayon::ThreadBuilder>> = OnceCell::new();
#[wasm_bindgen]
pub fn worker_initializer() -> JsValue {
TASKS.get_or_init(Injector::new);
array_of_2(wasm_bindgen::module(), wasm_bindgen::memory())
}
#[wasm_bindgen]
pub fn start_main_thread(workers: Array) {
// console_log::init_with_level(log::Level::Trace);
pub fn start_main_thread(num: usize) {
let tasks = TASKS.get().unwrap();
rayon::ThreadPoolBuilder::new()
.num_threads(workers.length() as _)
.spawn_handler(move |thread| {
Ok(workers.pop().unchecked_into::<Worker>().post_message({
let arr = Array::new();
arr.push(&wasm_bindgen::module());
arr.push(&wasm_bindgen::memory());
arr.push(&JsValue::from(Box::into_raw(Box::new(thread)) as u32));
arr.into()
}))
})
.num_threads(num)
.spawn_handler(|thread| Ok(tasks.push(thread)))
.build_global()
.unwrap_throw()
}
#[wasm_bindgen]
pub fn start_worker_thread(thread: *mut rayon::ThreadBuilder) {
// console_log::init_with_level(log::Level::Trace);
unsafe { Box::from_raw(thread) }.run()
pub fn start_worker_thread() {
let tasks = TASKS.get().unwrap();
loop {
if let crossbeam_deque::Steal::Success(task) = tasks.steal() {
return task.run();
}
}
}
#[wasm_bindgen(catch)]