{"id":20173516,"url":"https://github.com/w3reality/wasm-mt","last_synced_at":"2025-04-05T06:08:28.687Z","repository":{"id":45263646,"uuid":"266767872","full_name":"w3reality/wasm-mt","owner":"w3reality","description":"A multithreading library for Rust and WebAssembly","archived":false,"fork":false,"pushed_at":"2023-03-17T07:48:55.000Z","size":1561,"stargazers_count":209,"open_issues_count":3,"forks_count":13,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-29T05:08:34.937Z","etag":null,"topics":["rust","threading","wasm"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/w3reality.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-25T12:00:27.000Z","updated_at":"2025-02-17T21:32:30.000Z","dependencies_parsed_at":"2024-12-22T02:01:59.578Z","dependency_job_id":null,"html_url":"https://github.com/w3reality/wasm-mt","commit_stats":{"total_commits":62,"total_committers":3,"mean_commits":"20.666666666666668","dds":"0.19354838709677424","last_synced_commit":"a23b9d6a6a7e561824b8f511acfc07d82206d914"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/w3reality%2Fwasm-mt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/w3reality%2Fwasm-mt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/w3reality%2Fwasm-mt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/w3reality%2Fwasm-mt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/w3reality","download_url":"https://codeload.github.com/w3reality/wasm-mt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247294539,"owners_count":20915340,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rust","threading","wasm"],"created_at":"2024-11-14T01:36:28.046Z","updated_at":"2025-04-05T06:08:28.666Z","avatar_url":"https://github.com/w3reality.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- ⚠️  THIS IS A GENERATED FILE --\u003e\nwasm-mt\n=======\n\n[Docs](https://docs.rs/wasm-mt) |\n[GitHub](https://github.com/w3reality/wasm-mt) |\n[Crate](https://crates.io/crates/wasm-mt)\n\n[![crates][crates-badge]][crates-url]\n[![MIT licensed][mit-badge]][mit-url]\n[![CI][actions-badge]][actions-url]\n\n[crates-badge]: https://img.shields.io/crates/v/wasm-mt.svg\n[crates-url]: https://crates.io/crates/wasm-mt\n[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg\n[mit-url]: https://github.com/w3reality/wasm-mt/blob/master/LICENSE-MIT\n[actions-badge]: https://github.com/w3reality/wasm-mt/workflows/CI/badge.svg\n[actions-url]: https://github.com/w3reality/wasm-mt/actions\n\nA multithreading library for Rust and WebAssembly.\n\n`wasm-mt` helps you create and execute Web Worker based threads. You can program the threads simply using Rust closures and orchestrate them with `async/await`.\n\n#### Examples\n\n- **`wasm-mt-pool`** - Thread pool library based on `wasm-mt`. [ [crate](https://crates.io/crates/wasm-mt-pool) | [source](https://github.com/w3reality/wasm-mt/tree/master/crates/pool) ]\n\nYou can run all the following apps in browser!\n\n- **exec** - How to use \u003ccode\u003ewasm_mt\u003c/code\u003e. [ [live](https://w3reality.github.io/wasm-mt/examples/exec/index.html) | [source](https://github.com/w3reality/wasm-mt/tree/master/examples/exec) ]\n- **fib** - Computing a Fibonacci sequence with nested threads. [ [live](https://w3reality.github.io/wasm-mt/examples/fib/index.html) | [source](https://github.com/w3reality/wasm-mt/tree/master/examples/fib) ]\n- **executors** - Minimal serial/parallel executors using \u003ccode\u003ewasm_mt\u003c/code\u003e. [ [live](https://w3reality.github.io/wasm-mt/examples/executors/index.html) | [source](https://github.com/w3reality/wasm-mt/tree/master/examples/executors) ]\n- **parallel** - Julia set benchmark of serial/parallel executors. [ [live](https://w3reality.github.io/wasm-mt/examples/parallel/index.html) | [source](https://github.com/w3reality/wasm-mt/tree/master/examples/parallel) ]\n- **arraybuffers** - Demo of using \u003ccode\u003eWasmMt::new_with_arraybuffers()\u003c/code\u003e. [ [live](https://w3reality.github.io/wasm-mt/examples/arraybuffers/index.html) | [source](https://github.com/w3reality/wasm-mt/tree/master/examples/arraybuffers) ]\n\n#### Background and implementation\n\nThe preceding seminal work entitled [\"Multithreading Rust and Wasm\"](https://rustwasm.github.io/2018/10/24/multithreading-rust-and-wasm.html) by [@alexcrichton](https://github.com/alexcrichton) centers on [*Web Workers*](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API), *shared memory*, and [the WebAssembly threads proposal](https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md). Shared memory is built on top of [`SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) whose [availability across major browsers](https://caniuse.com/#feat=sharedarraybuffer) has been somewhat limited. Also, the rust-wasm thread implementation work, along with the threads proposal, seems still in progress.\n\nOn the contrary, Web Worker based multithreading in JavaScript has been [well supported for a long time](https://caniuse.com/#feat=webworkers). After experimenting, we have come up to a Rust ergonomic multithreading solution that does not require `SharedArrayBuffer`. It just works across all major browsers today and we named it `wasm-mt`.\n\nInternally, we use the [`postMessage()`](https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage) Web Worker API (through bindings provided by [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen)) to initialize spawned threads. And, importantly, we keep using `postMessage()` for dynamically sending Rust closures (serialized by [`serde_traitobject`](https://github.com/alecmocatta/serde_traitobject)) to the spawned threads. By doing so, the parent thread can `await` the results of the closures executed in the spawned thread. We have found that this approach is highly flexible for extension, too. For example, it is straightforward to augment `WasmMt::Thread` to support more customized inter-thread communication patterns.\n\nNote, however, that `wasm-mt` has some remarkable limitations compared to the ongoing shared memory based multithreading work led by `wasm-bindgen`. `wasm-mt` is not efficient in that it does **not include** support of the standard thread primitive operations:\n\n- shared memory based message passing and mutexes,\n- atomic instructions and efficient memory handling per [the threads proposal](https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md).\n\n#### Thanks\n\n- [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) developers\n- [@alecmocatta](https://github.com/alecmocatta) for the [serde_traitobject](https://github.com/alecmocatta/serde_traitobject) crate\n- [swc-project](https://github.com/swc-project) that facilitates the [wasm-mt-test](https://github.com/w3reality/wasm-mt/tree/master/crates/test) crate\n\n# Getting started\n\nRequirements:\n\n- rustc (nightly)\n- [`wasm-pack build`](https://github.com/rustwasm/wasm-pack#%EF%B8%8F-commands) with the [`--target no-modules`](https://rustwasm.github.io/docs/wasm-bindgen/reference/deployment.html#without-a-bundler) option\n\nCargo.toml:\n\n```toml\nwasm-mt = \"0.1\"\nserde = { version = \"1.0\", features = [\"derive\"] }\nserde_closure = \"0.3\"\n```\n\n# Creating a thread\n\nFirst, create a [`WasmMt`] thread builder with [`new`][WasmMt::new] and initialize it:\n\n```rust\nuse wasm_mt::prelude::*;\n\nlet pkg_js = \"./pkg/exec.js\"; // path to `wasm-bindgen`'s JS binding\nlet mt = WasmMt::new(pkg_js).and_init().await.unwrap();\n```\n\nThen, create a [`wasm_mt::Thread`][Thread] with the [`thread`][WasmMt::thread] function and initialize it:\n\n```rust\nlet th = mt.thread().and_init().await.unwrap();\n```\n\n# Executing a thread\n\nUsing the [`exec!`] macro, you can execute a closure in the thread and `await` the result:\n\n```rust\n// fn add(a: i32, b: i32) -\u003e i32 { a + b }\n\nlet a = 1;\nlet b = 2;\nlet ans = exec!(th, move || {\n    let c = add(a, b);\n\n    Ok(JsValue::from(c))\n}).await?;\nassert_eq!(ans, JsValue::from(3));\n```\n\nYou can also execute an [async closure] with `exec!`:\n\n```rust\n// use wasm_mt::utils::sleep;\n// async fn sub(a: i32, b: i32) -\u003e i32 {\n//    sleep(1000).await;\n//    a - b\n// }\n\nlet a = 1;\nlet b = 2;\nlet ans = exec!(th, async move || {\n    let c = sub(a, b).await;\n\n    Ok(JsValue::from(c))\n}).await?;\nassert_eq!(ans, JsValue::from(-1));\n```\n\n# Executing JavaScript in a thread\n\nUsing the [`exec_js!`] macro, you can execute JavaScript within a thread:\n\n```rust\nlet ans = exec_js!(th, \"\n    const add = (a, b) =\u003e a + b;\n    return add(1, 2);\n\").await?;\nassert_eq!(ans, JsValue::from(3));\n```\n\nSimilarly, use [`exec_js_async!`] for running asynchronous JavaScript:\n\n```rust\nlet ans = exec_js_async!(th, \"\n    const sub = (a, b) =\u003e new Promise(resolve =\u003e {\n        setTimeout(() =\u003e resolve(a - b), 1000);\n    });\n    return await sub(1, 2);\n\").await?;\nassert_eq!(ans, JsValue::from(-1));\n```\n\n# Making executors\n\nBy using [`wasm_mt:Thread`][Thread], you can easily create custom executors. One such example is the [`wasm-mt-pool` crate](https://crates.io/crates/wasm-mt-pool). It provides a [thread pool](https://doc.rust-lang.org/book/ch20-02-multithreaded.html#improving-throughput-with-a-thread-pool) that is based on the [work stealing] scheduling strategy.\n\nHere, for simplicity, we show the implementation of much more  straightforward executors: a serial executor and a parallel executor.\n\nFirst, prepare a `Vec\u003cwasm_mt::Thread\u003e` containing initialized threads:\n\n```rust\nlet mut v: Vec\u003cwasm_mt::Thread\u003e = vec![];\nfor i in 0..4 {\n    let th = mt.thread().and_init().await?;\n    v.push(th);\n}\n```\n\nThen, here's the executors in action. Note, in the latter case, we are using [`wasm_bindgen_futures::spawn_local`](https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen_futures/fn.spawn_local.html) to dispatch the threads in parallel.\n\n```rust\nconsole_ln!(\"🚀 serial executor:\");\nfor th in \u0026v {\n    console_ln!(\"starting a thread\");\n    let ans = exec!(th, move || Ok(JsValue::from(42))).await?;\n    console_ln!(\"ans: {:?}\", ans);\n}\n\nconsole_ln!(\"🚀 parallel executor:\");\nfor th in v {\n    spawn_local(async move {\n        console_ln!(\"starting a thread\");\n        let ans = exec!(th, move || Ok(JsValue::from(42))).await.unwrap();\n        console_ln!(\"ans: {:?}\", ans);\n    });\n}\n```\n\nObserve the starting/ending timing of each thread in the developer console:\n\n```text\n🚀 serial executor:\nstarting a thread\nans: JsValue(42)\nstarting a thread\nans: JsValue(42)\nstarting a thread\nans: JsValue(42)\nstarting a thread\nans: JsValue(42)\n🚀 parallel executor:\n(4) starting a thread\n(4) ans: JsValue(42)\n```\n\n[async closure]: https://github.com/rust-lang/rfcs/blob/master/text/2394-async_await.md#async--closures\n[work stealing]: https://en.wikipedia.org/wiki/Work_stealing\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fw3reality%2Fwasm-mt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fw3reality%2Fwasm-mt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fw3reality%2Fwasm-mt/lists"}