However, it crashes sporadically with errors like this:
Uncaught (in promise) RuntimeError: Atomics.wait cannot be called in this context
at core::core_arch::wasm32::atomic::memory_atomic_wait32::h96376a6414a86a87 (flume-wasm-atomics-test_bg.wasm:0xe12d2)
at std::sys::wasm::futex::futex_wait::h292a0a973fc726d3 (flume-wasm-atomics-test_bg.wasm:0xa5924)
at std::sys::wasm::locks::futex_mutex::Mutex::lock_contended::hd45bb12cab0c22e6 (flume-wasm-atomics-test_bg.wasm:0x702c4)
at std::sys::wasm::locks::futex_mutex::Mutex::lock::h73cff9beb960ea5f (flume-wasm-atomics-test_bg.wasm:0x98dd2)
at std::sync::mutex::Mutex<T>::lock::h1b6b582f0a571882 (flume-wasm-atomics-test_bg.wasm:0xdc6de)
at flume::wait_lock::h1c6a6297de59474f (flume-wasm-atomics-test_bg.wasm:0xaa943)
at flume::Shared<T>::recv::h41d724fcd222a605 (flume-wasm-atomics-test_bg.wasm:0x457ca)
at flume::Shared<T>::recv_sync::h75768094a9f2c6b2 (flume-wasm-atomics-test_bg.wasm:0x9caf9)
at flume::async::RecvFut<T>::poll_inner::hbd655e3c0d43e014 (flume-wasm-atomics-test_bg.wasm:0x328d0)
at <flume::async::RecvFut<T> as core::future::future::Future>::poll::hbd3ea43ef3f7793f (flume-wasm-atomics-test_bg.wasm:0xca7d9)
Note: This operation only works with an Int32Array or BigInt64Array that views a SharedArrayBuffer, and may not be allowed on the main thread. For a non-blocking, asynchronous version of this method, see Atomics.waitAsync().
My example itself doesn't block the main thread, it's just the wait_lock function that's blocking. If you look at my example, you'll notice I only used non-blocking code on the main thread.
However, using the spinlock implementation by enabling the spin feature doesn't work either because that uses thread::sleep which also blocks and therefore cannot be used in the main thread. This basically makes it impossible to use senders or receivers at all in a reliable way in multithreaded WebAssembly projects if either the sender or the receiver is on the main thread.
I propose to add a plain spinlock implementation of wait_lock without thread::sleep for WebAssembly like I did here: https://github.com/Astrabit-ST/flume/commit/d323799efea329c87a3a5a5b45cc76f46da278c2. Of course, this should be opt-in if it's implemented because not every WebAssembly project using flume is going to run into this issue.
I made a WebAssembly example at https://github.com/white-axe/flume-wasm-atomics-test that uses flume to send data between the main thread of a web browser and a web worker.
However, it crashes sporadically with errors like this:
This is happening because the
wait_lock
function is using a mutex or spinlock: https://github.com/zesterer/flume/blob/fcf384956a7badd003c4eca43da5174f4e0c86a0/src/lib.rs#L395-L416In my example, it's using the mutex implementation of
wait_lock
and the mutex is causing the error because it's blocking in the main thread of a web browser, and this is not allowed. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/wait:My example itself doesn't block the main thread, it's just the
wait_lock
function that's blocking. If you look at my example, you'll notice I only used non-blocking code on the main thread.However, using the spinlock implementation by enabling the
spin
feature doesn't work either because that usesthread::sleep
which also blocks and therefore cannot be used in the main thread. This basically makes it impossible to use senders or receivers at all in a reliable way in multithreaded WebAssembly projects if either the sender or the receiver is on the main thread.I propose to add a plain spinlock implementation of
wait_lock
withoutthread::sleep
for WebAssembly like I did here: https://github.com/Astrabit-ST/flume/commit/d323799efea329c87a3a5a5b45cc76f46da278c2. Of course, this should be opt-in if it's implemented because not every WebAssembly project using flume is going to run into this issue.