Hello! I currently have a PR up for review in the
wasm_bindgen project, and I think it would be helpful to have some more eyes on it. Especially if you're familiar with multithreaded code, atomics, and the Webassembly threading proposal!
I've been experimenting with sharing a Rust object across WebWorkers. For the most part, I followed @alexcrichton's amazing raytracing example. But Alex's example sends a different pointer to each worker, which then owns the pointer. My minimal repro shows how I share the same threadsafe object across many workers.
But my WebWorkers keep throwing errors:
"Error: recursive use of an object detected which would lead to unsafe aliasing in rust".
...except my code doesn't have any recursion.
But that's okay, because the error message actually means that I've broken Rust's aliasing rules. Someone must be calling an
...except my code doesn't have any
I tracked the error down to
wasm_bindgen::__rt::WasmRefCell, a small reimplementation of
self.borrow was data racing like nobody's business, often underflowing to
usize::max_value()! That's a sentinel value that says someone is writing to the object.
So we have a data race in "safe Rust" (at least in the sense that I didn't use any
unsafe blocks, not in the sense that it's okay for me to access
__wbg_ptr and toss those pointers to other WebWorkers). This isn't necessarily
WasmRefCell's fault. It's not a
Sync object, and it wasn't designed to be a
Sync object. But making it thread-safe, by replacing
borrow: Cell<usize> with an
AtomicUsize, solves my problem very neatly, and I don't really have a way to keep using threaded wasm Rust code without it. For now, I'm going to use my PR to keep developing my project.
That said, my proposal does add overhead to, um, every call across the JS/Rust boundary. The compiler is usually able to eliminate the store instructions in
WasmRefCell, but that's no longer true when those store instructions are atomic.
What do people think? Should this use of atomics live behind a command-line flag or config option? Should Rust's safety guarantees extend to sharing an object across WebWorkers in a browser, at least when that object is