Skip to content

Commit

Permalink
Add 'non-blocking' function attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
lukewagner committed Jan 20, 2025
1 parent f0dab1b commit c8be8a4
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 8 deletions.
32 changes: 29 additions & 3 deletions design/mvp/Async.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,34 @@ component-level function that has been [lifted] from Core WebAssembly with the
function that does not have the `async` option set (which is the default and
only option prior to Preview 3). Thus, the sync/async distinction appears
only independently in how a component-level function is *implemented* or
*called*.
*called*. This lack of distinction helps to avoid the classic ["What Color Is
Your Function?"][Color] problem.

Function types *may* be given an optional `non-blocking` function attribute to
indicate that the caller should assume that the callee doesn't block. However,
`non-blocking` is ignored at validation- and run-time and thus a `non-blocking`
function may in fact block (and indeed there are valid use cases for doing so,
such as in performance-insensitive virtualization scenarios). Therefore,
`non-blocking` is primarily intended as a *hint* to inform source-language
bindings to generate synchronous source-level function signatures (lifted and
and lowered without setting the `async` Canonical ABI option). Importantly,
since "blocking" is the default, interface authors are encouraged to apply
`non-blocking` judiciously.

Since in many languages `new` expressions cannot be async, `constructor`
functions also imply `non-blocking`. In the future, [getters and setters] would
also imply `non-blocking`. For example:
```wit
interface filesystem {
resource file {
constructor(); // non-blocking by default
is-closed: non-blocking func() -> bool; // explicitly non-blocking
read: func(num-bytes: u32) -> result<list<u8>>; // blocking by default
```
If a resource-type has a potentially-blocking constructor, it can simply use
`static new: func(...) -> my-resource` instead; `constructor` has no advantages
beyond more-idiomatic bindings generation in some languages.


### Task

Expand Down Expand Up @@ -591,8 +618,6 @@ Native async support is being proposed incrementally. The following features
will be added in future chunks roughly in the order list to complete the full
"async" story, with a TBD cutoff between what's in [WASI Preview 3] and what
comes after:
* `nonblocking` function type attribute: allow a function to declare in its
type that it will not transitively do anything blocking
* define what `async` means for `start` functions (top-level await + background
tasks), along with cross-task coordination built-ins
* `subtask.cancel`: allow a supertask to signal to a subtask that its result is
Expand Down Expand Up @@ -646,6 +671,7 @@ comes after:
[Use Cases]: ../high-level/UseCases.md
[Blast Zone]: FutureFeatures.md#blast-zones
[Reentrance]: Explainer.md#component-invariants
[Getters And Setters]: https://github.com/WebAssembly/component-model/issues/235

[stack-switching]: https://github.com/WebAssembly/stack-switching/
[JSPI]: https://github.com/WebAssembly/js-promise-integration/
Expand Down
13 changes: 11 additions & 2 deletions design/mvp/Binary.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,11 @@ valtype ::= i:<typeidx> => i
| pvt:<primvaltype> => pvt
resourcetype ::= 0x3f 0x7f f?:<funcidx>? => (resource (rep i32) (dtor f)?)
| 0x3e 0x7f f:<funcidx> cb?:<funcidx>? => (resource (rep i32) (dtor async f (callback cb)?))
functype ::= 0x40 ps:<paramlist> rs:<resultlist> => (func ps rs)
functype ::= 0x40 sig:<funcsig> => (func sig)
| 0x3d attrs:<funcattrs> sig:<funcsig> => (func attrs sig)
funcattrs ::= 0x00 =>
| 0x01 => non-blocking
funcsig ::= ps:<paramlist> rs:<resultlist> => ps rs
paramlist ::= lt*:vec(<labelvaltype>) => (param lt)*
resultlist ::= 0x00 t:<valtype> => (result t)
| 0x01 0x00 =>
Expand Down Expand Up @@ -386,7 +390,10 @@ Notes:
export, respectively, in the same scope (component, component type or
instance type).
* Validation of `[constructor]` names requires that the `func` returns a
`(result (own $R))`, where `$R` is the resource labeled `r`.
`(result (own $R))`, where `$R` is the resource labeled `r`. Additionally,
the function type *should* have the `non-blocking` attribute. In a future
pre-1.0 breaking change, validation will *require* the `non-blocking`
attribute.
* Validation of `[method]` names requires the first parameter of the function
to be `(param "self" (borrow $R))`, where `$R` is the resource labeled `r`.
* Validation of `[method]` and `[static]` names ensures that all field names
Expand Down Expand Up @@ -487,6 +494,8 @@ named once.
* The opcodes (for types, canon built-ins, etc) should be re-sorted
* The two `list` type codes should be merged into one with an optional immediate.
* The `0x00` prefix byte of `importname'` and `exportname'` will be removed or repurposed.
* Merge the two `functype` opcodes.
* Require `non-blocking` on `[constructor]` functions.


[`core:byte`]: https://webassembly.github.io/spec/core/binary/values.html#binary-byte
Expand Down
8 changes: 6 additions & 2 deletions design/mvp/Explainer.md
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ defvaltype ::= bool
valtype ::= <typeidx>
| <defvaltype>
resourcetype ::= (resource (rep i32) (dtor async? <funcidx> (callback <funcidx>)?)?)
functype ::= (func (param "<label>" <valtype>)* (result <valtype>)?)
functype ::= (func non-blocking? (param "<label>" <valtype>)* (result <valtype>)?)
componenttype ::= (component <componentdecl>*)
instancetype ::= (instance <instancedecl>*)
componentdecl ::= <importdecl>
Expand Down Expand Up @@ -783,7 +783,11 @@ shared-nothing functions, resources, components, and component instances:

The `func` type constructor describes a component-level function definition
that takes a list of uniquely-named `valtype` parameters and optionally returns
a `valtype`.
a `valtype`. Function types can optionally be annotated with a `non-blocking`
attribute which has no semantic effect and is ignored at validation- and
run-time, serving primarily as a hint that tells bindings generators to lift
and lower without setting the `async` `canonopt` (see the [async
explainer](Async.md#sync-and-async-functions) for more details).

The `resource` type constructor creates a fresh type for each instance of the
containing component (with "freshness" and its interaction with general
Expand Down
3 changes: 2 additions & 1 deletion design/mvp/WIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,7 @@ keyword ::= 'as'
| 'include'
| 'interface'
| 'list'
| 'non-blocking'
| 'option'
| 'own'
| 'package'
Expand Down Expand Up @@ -1295,7 +1296,7 @@ typedef-item ::= resource-item
func-item ::= id ':' func-type ';'
func-type ::= 'func' param-list result-list
func-type ::= 'non-blocking'? 'func' param-list result-list
param-list ::= '(' named-type-list ')'
Expand Down

0 comments on commit c8be8a4

Please sign in to comment.