Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for WASM targets #20

Open
notgull opened this issue Dec 6, 2023 · 1 comment
Open

Add support for WASM targets #20

notgull opened this issue Dec 6, 2023 · 1 comment
Labels
help wanted Extra attention is needed

Comments

@notgull
Copy link
Member

notgull commented Dec 6, 2023

In WebAssembly targets, blocking is unimplemented in the standard library except for target_feature = "atomics". Therefore blocking cannot happen until that feature is used. But, we can compile conditionally for that feature.

On web browsers, there is an Atomics API that can be used to block in Web Workers, but not on the main thread. So we could conditionally select that on web (like getrandom does), and then try to get that API. Then, if we're in a web worker, block, and if we're in the main thread, panic.

We could even have a try_park() method that allows users to handle the case of if they cannot actually park, because they're on the main thread. This would allow users to handle the case of not parking.

It would be nice to implement this in parking, that way it can be bubbled up to other primitives in smol.

See this comment for more info.

@sorcio
Copy link

sorcio commented Apr 17, 2024

This is interesting to me because I want to use async-channels in a web browser context. I'm willing to help, though I want to understand the issue better.

On web browsers, there is an Atomics API that can be used to block in Web Workers, but not on the main thread. So we could conditionally select that on web (like getrandom does), and then try to get that API. Then, if we're in a web worker, block, and if we're in the main thread, panic.

In a way, this is sort of what already happens with std::sync::Mutex, at least on nightly and with the atomics target feature. Instead of a panic you get a browser-defined JS exception telling you that you cannot wait in the main thread context. To the best of my understanding, it's not UB for a thread to terminate during futex_wait, so std::sync::Mutex should tolerate this well.

An annoyance is that std needs to be built with atomics support, which is not by default, so a user will usually need to pass -Z build_std to cargo. We could skip the std implementation and just use compiler intrinsics like parking_lot does to work around that, but now you maintain a futex implementation.

We could even have a try_park() method that allows users to handle the case of if they cannot actually park, because they're on the main thread. This would allow users to handle the case of not parking.

There is no clean way to detect that parking is not allowed. On web, you can check if you have a Window global context in a hacky way. Alternatively, one can catch a failed wait. WASM does not directly allow that, but you can jump to JS and call Atomics.wait and catch the exception there (or use js_sys to do this for you). This might work in more platforms than just web, but still makes assumptions on the platform and still depends on something like wasm-bindgen. On the other hand, I think the issue currently only exists in such platforms (browsers and, I assume, Node?). Maybe a new tiny "can_suspend" crate can expose this.

I'm not sure this API is very useful, though. How can consuming code recover from an error? Do you have a use case in mind? Maybe it could be a later extension, if the panicking/trapping variant is already useful on its own. Though I might be too hasty, since I'm not familiar with the whole smol context.


The minimal amount of work that I can see here is not to change anything in this crate, and make the cfg guards on target_family = "wasm" conditional to target_feature = "atomics" on higher level code (event-listener, async-channels are probably enough for my own case).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Development

No branches or pull requests

2 participants