-
Notifications
You must be signed in to change notification settings - Fork 1
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
[thread-spawn] Allow more function types to be spawned #15
Conversation
cc: @rossberg, I think the right spec notation is likely |
As discussed [here], limiting which function types can be spawned is... well, limiting. Previously, only allowing a single `i32` parameter meant that toolchains would have to create a closure, likely in shared memory, in order to pass more information to the spawned thread. This would make sense when the implementation uses `pthread_create`, e.g., but could be limiting in other cases. [here]: #3 (comment) Though that discussion never pinpointed any specific languages where this might be a problem, the limit was a bit artificial. I propose we start with a proposal that is as general as possible and whittle down from there. This change allows the spawned function to take any Wasm parameters with the understanding that this moves the complexity from the toolchain to the engine (at least when using pthreads). We still retain the limitation that the spawned function must not return a value because there is no place to return it to: (a) the thread may start executing long after control flow has progressed from the spawn point and (b) it doesn't seem advisable to me yet to add promises/futures/etc.
306d45b
to
021faf4
Compare
I'd probably write |
proposals/thread-spawn/Overview.md
Outdated
| Validation | Valid with type `[i32, i32] -> []`; also, the function referred to must have type `[i32] -> []` and be `shared` | | ||
| Execution | With function index `f` and stack values `n` and `c`, enqueue `n` "parallel" invocations of `f` passing `c`; immediately return | | ||
| Validation | Valid with type `[i32, t*] -> []` when the function referred to has type `[t*] -> []` and is `shared` | | ||
| Execution | With function index `f` and stack values [`n`, `p*`], enqueue `n` "parallel" invocations of `f` passing `p*`; immediately return | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: v*
instead of p*
if we have thread.id
, then thread.spawn
might need to take a separate i32
arg for the ID (note: allowing thread.spawn
to create multiple threads would interfere with this somewhat unless we had some mapping convention for the ID).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed that more discussion is needed about the multiple threads; I've been thinking about it and have a couple of ideas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's what I was thinking last week (should have just written it out!): if we end up going with "thread.spawn
creates multiple threads," thread.id
could return two values, (1) the i32
arg passed initially and (2) an i32
for its ID within the group. It seemed to me those two values could be efficiently combined (e.g., addition, multiplication, shifting) to get at the thread-local memory for a specific thread, however the toolchain/thread framework might choose to do so.
execution has already progressed past the `thread.spawn` instruction. | ||
2. _simplicity_: implementation-wise, if engines map `thread.spawn` to OS threads, they may be able | ||
to do less wrapping and unwrapping if `f` expects a single parameter (as do OS threads). | ||
- _no return values_: by preventing return values, this design can avoid adding a "thread" handle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some design discussion here
maybe we want thread.spawn
to be fallible, in which case we need a return value to signal this
some Web platform people may desire a terminate
instruction that the spawner can call on a spawned thread, in which case we'd need thread.spawn
to return some kind of rudimentary thread handle
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another approach here would be for the toolchain to take responsibility for how this gets communicated to the thread and have the thread end itself; cancelling threads can be a tricky business. There's also the thread.exit
idea that might apply here; see "what about exiting a thread?".
As discussed here, limiting which function types can be spawned is... well, limiting. Previously, only allowing a single
i32
parameter meant that toolchains would have to create a closure, likely in shared memory, in order to pass more information to the spawned thread. This would make sense when the implementation usespthread_create
, e.g., but could be limiting in other cases.Though that discussion never pinpointed any specific languages where this might be a problem, the limit was a bit artificial. I propose we start with a proposal that is as general as possible and whittle down from there. This change allows the spawned function to take any Wasm parameters with the understanding that this moves the complexity from the toolchain to the engine (at least when using pthreads).
We still retain the limitation that the spawned function must not return a value because there is no place to return it to: (a) the thread may start executing long after control flow has progressed from the spawn point and (b) it doesn't seem advisable to me yet to add promises/futures/etc.