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

Adding in Futures 0.3 support to wasm-bindgen-futures #1507

Merged
merged 3 commits into from
May 6, 2019

Conversation

Pauan
Copy link
Contributor

@Pauan Pauan commented May 2, 2019

I haven't tested this yet, but it probably works.

I put everything behind the nightly feature. I'm open to changing the name.

Unfortunately I can't really add unit tests, because the wasm-bindgen-test crate requires Futures 0.1

@Pauan
Copy link
Contributor Author

Pauan commented May 2, 2019

I tried to test this, but I keep running into #1501 (comment) and I wasn't able to compile any of the examples.

Copy link
Contributor

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code-wise looks great to me, thanks @Pauan! I had some questions inline, but I might recommend renaming nightly to std-futures or something like that? It'll only be nightly very temporarily :)

F: Future<Output = ()> + 'static,
{
struct Task {
future: Mutex<Option<Pin<Box<dyn Future<Output = ()> + 'static>>>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the Future here is fundamentally non-Send, is the Mutex/Atomic* required or could they be replaced with non-threadsafe variants?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, orthogonally, I wasn't quite sure why I initially saw Option here, but is the idea that you can drop the future at any time but there may still be lingering handles to the Task for awhile longer while events are processed throughout the system?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The atomic stuff isn't needed, it's just a holdover from when I tried to make it thread safe (and then later gave up).

The reason for the Option is because the Future might return Poll::Ready and also call waker.wake(). That would end up causing an infinite loop, so the Option lets us avoid that.

Sure, that's technically against the Future contract, but I like to make the code rock solid so it can survive even bad Futures.

It also has the benefit that it can drop the Future immediately when it returns Poll::Ready (rather than at some potentially far-future time when the Task is eventually dropped).

Because the Waker contains an Arc<Task>, it's theoretically possible that the Future will never get dropped (if someplace somewhere keeps a hold of the Waker). So the Option lets us fix that.

impl ArcWake for Task {
fn wake_by_ref(arc_self: &Arc<Self>) {
// TODO can this be more relaxed ?
if !arc_self.is_queued.swap(true, Ordering::SeqCst) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be swapped for if swap(true) { return } to avoid indentation where we can?


impl ArcWake for Task {
fn wake_by_ref(arc_self: &Arc<Self>) {
// TODO can this be more relaxed ?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically the ordering doesn't matter at all today in the sense that all orderings are equivalent when you're dealing with one thread of code. For multithreaded code wasm has no concept of orderings, so we'll want to stick SeqCst everywhere

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's good to know about multi-threaded wasm.

rejected: oneshot::Receiver<JsValue>,
callbacks: Option<(Closure<FnMut(JsValue)>, Closure<FnMut(JsValue)>)>,
}
#[cfg(not(feature = "nightly"))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we'll probably want to have the standard library futures support in its own module. We don't want enabling the nightly feature to break this crate (features should be additive in terms of functionality) for existing users. That does mean that if nightly is enabled it'll pull in two implementations of futures, but I think that's ok since the linker will eliminate them if they're not used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with that.

@Pauan
Copy link
Contributor Author

Pauan commented May 4, 2019

Okay, I addressed all the feedback.

@alexcrichton alexcrichton merged commit a85335d into rustwasm:master May 6, 2019
@alexcrichton
Copy link
Contributor

👍 nice!

@Pauan Pauan deleted the futures-0.3 branch May 6, 2019 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants