|
| 1 | +# Using threads in WebAssembly |
| 2 | + |
| 3 | +## Background |
| 4 | + |
| 5 | +While the WebAssembly spec defines [atomic operations](https://github.com/WebAssembly/threads), |
| 6 | +it does not define a way to create threads. This means that WebAssembly modules can't create |
| 7 | +threads themselves, and the host environment must provide a way to create threads and run |
| 8 | +WebAssembly modules on them. |
| 9 | + |
| 10 | +## [`wasi-threads`](https://github.com/WebAssembly/wasi-threads) proposal |
| 11 | + |
| 12 | +The WebAssembly System Interface (WASI) had a proposal for adding thread creation APIs to WASI. |
| 13 | +The proposal was implemented in several WASI host runtimes, including Wasmtime and wasm-micro-runtime, |
| 14 | +but it was [withdrawn in August 2023](https://github.com/WebAssembly/wasi-threads/issues/48#issuecomment-1696407630) in favor of [shared-everything-threads](https://github.com/WebAssembly/shared-everything-threads) proposal. However, the shared-everything-threads proposal is still in the early stages of development and is not yet available in any WASI host runtime. So, for now, we are employing the `wasi-threads` ABI in SwiftWasm to provide thread support immediately. |
| 15 | + |
| 16 | +The `wasi-threads` feature is only available in the `wasm32-unknown-wasip1-threads` target triple, which is explicitly distinct from the `wasm32-unknown-wasi` target triple. |
| 17 | + |
| 18 | +The `wasm32-unknown-wasip1-threads` target triple is only available in the nightly Swift SDK for WebAssembly. |
| 19 | + |
| 20 | +You can run WebAssembly programs built with the `wasm32-unknown-wasip1-threads` target by using the `wasmtime` runtime with the `--wasi threads` flag. |
| 21 | +Check [a recent nightly Swift SDK release](https://github.com/swiftwasm/swift/releases) and how to install it [here](./setup-snapshot.md). |
| 22 | + |
| 23 | +```console |
| 24 | +# Assume you are using swift-DEVELOPMENT-SNAPSHOT-2024-12-04-a toolchain |
| 25 | +$ swift sdk install https://github.com/swiftwasm/swift/releases/download/swift-wasm-DEVELOPMENT-SNAPSHOT-2024-12-05-a/swift-wasm-DEVELOPMENT-SNAPSHOT-2024-12-05-a-wasm32-unknown-wasip1-threads.artifactbundle.zip --checksum 1796ae86f3c90b45d06ee29bb124577aa4135585bbd922430b6d1786f855697d |
| 26 | +$ swift build --swift-sdk wasm32-unknown-wasip1-threads |
| 27 | +# Enable the `wasi-threads` feature in wasmtime |
| 28 | +$ wasmtime --wasi threads .build/debug/Example.wasm |
| 29 | +``` |
| 30 | + |
| 31 | +Note that even with the `wasi-threads` feature, the default concurrency execution model is still single-threaded as we have not yet ported libdispatch. The `wasi-threads` feature is only used to provide a low-level `pthread` API for creating threads. |
| 32 | + |
| 33 | +## `WebWorkerTaskExecutor` - shared-everything concurrency |
| 34 | + |
| 35 | +We provide `WebWorkerTaskExecutor`, a [`TaskExecutor`](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0417-task-executor-preference.md) implementation that runs `Task`s in a Web Worker. This allows you to run Swift code concurrently in a Web Worker sharing the same memory space. |
| 36 | + |
| 37 | +This feature is available in the `JavaScriptKit` package and you need to use `wasm32-unkonwn-wasip1-threads` target and [`SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) to use it. |
| 38 | + |
| 39 | +See more details in the following links: |
| 40 | + |
| 41 | +- [Add `WebWorkerTaskExecutor` · Pull Request #256 · swiftwasm/JavaScriptKit](https://github.com/swiftwasm/JavaScriptKit/pull/256) |
| 42 | +- [JavaScriptKit/Examples/Multithreading at main · swiftwasm/JavaScriptKit](https://github.com/swiftwasm/JavaScriptKit/tree/main/Examples/Multithreading) |
| 43 | +- [WebWorkerTaskExecutor | Documentation](https://swiftpackageindex.com/swiftwasm/javascriptkit/main/documentation/javascripteventloop/webworkertaskexecutor) |
| 44 | + |
| 45 | +## `WebWorkerKit` - shared-nothing concurrency |
| 46 | + |
| 47 | +If you can't use `SharedArrayBuffer` or want to run Swift code in a separate memory space, you can use `WebWorkerKit`. `WebWorkerKit` is a library that provides a way to run Swift Distributed Actors in their own worker "thread" in a Web Worker. It's message-passing based and allows you to run Swift code concurrently in a Web Worker without sharing memory space. |
| 48 | + |
| 49 | +Check the repository for more details: [swiftwasm/WebWorkerKit: A way of running Swift Distributed Actors in their own worker "thread"](https://github.com/swiftwasm/WebWorkerKit) |
0 commit comments