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

Threadsafe futures #1514

Merged
merged 18 commits into from
Jul 19, 2019
Merged

Threadsafe futures #1514

merged 18 commits into from
Jul 19, 2019

Conversation

ibaryshnikov
Copy link
Member

Closes #1379

Changes:

  • Added extern function wait_async, which does the same as Atomics::waitAsync
  • Removed impl Notify for Package, also removed Send + Sync markers for Package
  • Added Waker struct instead, which implements Notify
  • Used Waker instead of Package to notify the executor

crates/js-sys/src/lib.rs Outdated Show resolved Hide resolved
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.

I think the general structure that this is going to want to take is that spawning a future creates two main allocations. One is a Rc (or something like that) which holds the future itself. Another is an Arc which has some shared state. When creating a waker the Arc is what's shared, and its notify implementation will probably look like:

if !self.notified.swap(true) {
    // run an atomic notify at the address of `&self.notified`
}

In the poll loop I think it would look roughly like:

let promise = wait_async_on(&self.notified);
while self.notified.swap(true) {
    // do the poll
}
promise.then(&poll_again);

crates/futures/src/polyfill.js Outdated Show resolved Hide resolved
@ibaryshnikov
Copy link
Member Author

Does it mean that the state with Polling | Notified | Waiting will be removed, and there will be only true or false?

@alexcrichton
Copy link
Contributor

Oh what I gisted was just a straw man, it may be that two bits are still needed rather than one for information exchange.

@ibaryshnikov
Copy link
Member Author

@alexcrichton the pr is not tested yet, I pushed changes to check the design.
There are several places to check: first, I removed impl Notify for Package. Then, instead of &me, there is &me.waker passed to poll_future_notify.
And I moved code from impl Notify for Package to fn poll_again
Inside fn poll_again Promise::resolve was replaced with wait_async
Did I get your idea right?

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.

This looks along the right lines yeah! There's probably a lot of devils in the details, but I think the general direction here is where we want to go.

crates/futures/src/lib.rs Outdated Show resolved Hide resolved
@ibaryshnikov
Copy link
Member Author

@alexcrichton I think I hit the wall here: #1525
There's a need to either make js snippets work with node target or replace the snippet with polyfill with the wasm equivalent. What do you think is better?

@alexcrichton
Copy link
Contributor

Yeah it may be some time before snippets work on Node, so it's probably best to not block this on that. Perhaps the polyfill could be implemented in Rust though?

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.

Some great progress!

crates/futures/src/polyfill.rs Outdated Show resolved Hide resolved
crates/futures/src/polyfill.js Outdated Show resolved Hide resolved
crates/futures/src/polyfill.rs Outdated Show resolved Hide resolved
crates/futures/src/polyfill.rs Outdated Show resolved Hide resolved
crates/futures/src/polyfill.rs Outdated Show resolved Hide resolved
crates/futures/src/lib.rs Outdated Show resolved Hide resolved
crates/futures/src/lib.rs Outdated Show resolved Hide resolved
crates/futures/src/lib.rs Outdated Show resolved Hide resolved
crates/futures/src/lib.rs Outdated Show resolved Hide resolved
crates/futures/src/lib.rs Outdated Show resolved Hide resolved
@ibaryshnikov
Copy link
Member Author

@alexcrichton thank you for a great review! I fixed most of the places, but still have some questions, like usage of AtomicI32, or simplifying Waker struct. Btw, it looks working, and after increasing default timeout from 0 to 10ms the performance looks fine. So it's probably a time to start making changes to raytrace_parallel example itself?

crates/futures/src/lib.rs Outdated Show resolved Hide resolved
crates/futures/src/lib.rs Outdated Show resolved Hide resolved
crates/futures/src/polyfill.rs Outdated Show resolved Hide resolved
crates/futures/src/polyfill.rs Outdated Show resolved Hide resolved
crates/futures/src/polyfill.rs Outdated Show resolved Hide resolved
crates/futures/src/atomics.rs Outdated Show resolved Hide resolved
crates/futures/src/polyfill.rs Outdated Show resolved Hide resolved
crates/futures/src/polyfill.rs Outdated Show resolved Hide resolved
crates/futures/src/polyfill.rs Outdated Show resolved Hide resolved
crates/futures/src/polyfill.rs Outdated Show resolved Hide resolved
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.

This is some comments on the polyfill at least, I'll try to get to the futures implementation later this week!

@ibaryshnikov
Copy link
Member Author

@alexcrichton I fixed most of the places, but still have some where I'm not sure, like what to do with closures, and the contents of the Waker struct, which is currently

struct Waker {
    value: AtomicI32,
    notified: AtomicBool,
}

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.

Sorry for the delays, travel got the best of me! But yes the notified field can be removed and just value needs to be there, and we can use flags in value to indicate whether polling needs to happen and such.

crates/futures/src/atomics.rs Outdated Show resolved Hide resolved
@ibaryshnikov
Copy link
Member Author

Updated to the latest master (I hope I didn't miss anything). Removed notified field, there's only value now inside Waker.
Can we summarize, what's left to do in this pr? I'm kind of lost in the comments.

Not implemented yet, and the one there doesn't work with atomics! (we'll
get around to this soon-ish)
Use the atomics support now implemented!
* Remove now-unneeded `State` enum
* Remove timeout argument from polyfill since we don't need it
* Call `Atomics.waitAsync` if it's available instead of using our polyfill
* Remove some extraneous dead code from the polyfill
* Add a `val: i32` argument to the polyfill
* Simplify the flow of futures with `Package` since `waitAsync` handles
  all the heavy lifting for us.
* Remove `Arc<Package>` and just use `Package`
* Remove `RefCell` from inside of `Package` now that it is no longer
  needed.
Turns out it's the exact same for both before and after atomics, so
let's use the same definition!
* Use "legacy" instead of "stable" since `futures 0.1` is quicly
  becoming "legacy"
* Rename "atomics" to "legacy_atomics" to leave room for the
  libstd-based futures atomics version.
* Rename "polyfill" to "wait_async_polyfill" to specify what it's
  polyfilling.
@alexcrichton alexcrichton changed the title [WIP] Threadsafe futures Threadsafe futures Jul 18, 2019
@alexcrichton
Copy link
Contributor

Ok thanks for the update @ibaryshnikov!

I've added a few more commits which cleaned up a few things (good chunks of the old future_to_promise implementation aren't necessary when using waitAsync) and reorganized some files a bit. I also hooked up the parallel raytrace example and can confirm it's all plumbed together and at least rudimentarily working.

If CI is green and you're good with this I think it's good to merge!

@ibaryshnikov
Copy link
Member Author

@alexcrichton I'm good with this. Thanks for moving this forvard! And thanks for your comments, I've learned a lot from this pr!)

@alexcrichton
Copy link
Contributor

Ok let's merge then, thanks so much again @ibaryshnikov!

@maxammann
Copy link

I think I found a usecase which is incomatible with this PR: #3048

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.

Implement a threadsafe version of wasm-bindgen-futures
3 participants