Skip to content

Commit 41daa8d

Browse files
committed
Update Explainer WIT summaries to match #498
1 parent ffcbfde commit 41daa8d

File tree

1 file changed

+98
-106
lines changed

1 file changed

+98
-106
lines changed

design/mvp/Explainer.md

Lines changed: 98 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,10 +1310,10 @@ and empty results.
13101310
🔀 The `async` option specifies that the component wants to make (for imports)
13111311
or support (for exports) multiple concurrent (asynchronous) calls. This option
13121312
can be applied to any component-level function type and changes the derived
1313-
Canonical ABI significantly. See the [async explainer](Async.md) for more
1314-
details. When a function signature contains a `future` or `stream`, validation
1315-
of `canon lower` requires the `async` option to be set (since a synchronous
1316-
call to a function using these types is highly likely to deadlock).
1313+
Canonical ABI significantly. See the [async explainer] for more details. When
1314+
a function signature contains a `future` or `stream`, validation of `canon
1315+
lower` requires the `async` option to be set (since a synchronous call to a
1316+
function using these types is highly likely to deadlock).
13171317

13181318
🔀 The `(callback ...)` option may only be present in `canon lift` when the
13191319
`async` option has also been set and specifies a core function that is
@@ -1324,7 +1324,7 @@ validated to have the following core function type:
13241324
(param $payload i32)
13251325
(result $done i32))
13261326
```
1327-
Again, see the [async explainer](Async.md) for more details.
1327+
Again, see the [async explainer] for more details.
13281328

13291329
🔀 The `always-task-return` option may only be present in `canon lift` when
13301330
`post-return` is not set and specifies that even synchronously-lifted functions
@@ -1547,8 +1547,8 @@ transferring ownership of the newly-created resource to the export's caller.
15471547

15481548
##### 🔀 Async built-ins
15491549

1550-
See the [async explainer](Async.md) for high-level context and terminology and
1551-
the [Canonical ABI explainer] for detailed runtime semantics.
1550+
See the [async explainer] for high-level context and terminology and the
1551+
[Canonical ABI explainer] for detailed runtime semantics.
15521552

15531553
###### 🔀 `context.get`
15541554

@@ -1657,10 +1657,10 @@ where `event` is defined in WIT as:
16571657
variant event {
16581658
none,
16591659
subtask(subtask-index, subtask-state),
1660-
stream-read(stream-index, read-status),
1661-
stream-write(stream-index, write-status),
1662-
future-read(future-index, read-status),
1663-
future-write(future-index, write-status),
1660+
stream-read(stream-index, copy-result),
1661+
stream-write(stream-index, copy-result),
1662+
future-read(future-index, copy-result),
1663+
future-write(future-index, copy-result),
16641664
task-cancelled,
16651665
}
16661666
@@ -1672,7 +1672,6 @@ enum subtask-state {
16721672
cancelled-before-returned,
16731673
}
16741674
```
1675-
16761675
The `waitable-set.wait` built-in waits for any one of the [waitables] in the
16771676
given [waitable set] `s` to make progress and then returns an `event`
16781677
describing the event. The `event` `none` is never returned. Waitable sets
@@ -1685,6 +1684,13 @@ can be started (via export call) or resumed while the current task blocks. If
16851684
code until `wait` returns (however, *other* component instances may execute
16861685
code in the interim).
16871686

1687+
A `subtask` event notifies the supertask that its subtask is now in the given
1688+
state (the meanings of which are described by the [async explainer]).
1689+
1690+
The meanings of the `{stream,future}-{read,write}` events as well as the
1691+
definition of `copy-result` is given as part [`stream.read` and
1692+
`stream.write`](#-streamread-and-streamwrite) below.
1693+
16881694
In the Canonical ABI, the `event-code` return value provides the `event`
16891695
discriminant and the case payloads are stored as two contiguous `i32`s at the
16901696
8-byte-aligned address `payload-addr`. (See also [`canon_waitable_set_wait`]
@@ -1791,119 +1797,106 @@ An analogous relationship exists among `readable-future-end<T>`,
17911797

17921798
###### 🔀 `stream.read` and `stream.write`
17931799

1794-
| Synopsis | |
1795-
| -------------------------------------------- | --------------------------------------------------------------------------- |
1796-
| Approximate WIT signature for `stream.read` | `func<T>(e: readable-stream-end<T>, b: writable-buffer<T>) -> read-status` |
1797-
| Approximate WIT signature for `stream.write` | `func<T>(e: writable-stream-end<T>, b: readable-buffer<T>) -> write-status` |
1798-
| Canonical ABI signature | `[stream-end:i32 ptr:i32 num:i32] -> [i32]` |
1800+
| Synopsis | |
1801+
| -------------------------------------------- | ---------------------------------------------------------------------------------- |
1802+
| Approximate WIT signature for `stream.read` | `func<T>(e: readable-stream-end<T>, b: writable-buffer<T>) -> option<copy-result>` |
1803+
| Approximate WIT signature for `stream.write` | `func<T>(e: writable-stream-end<T>, b: readable-buffer<T>) -> option<copy-result>` |
1804+
| Canonical ABI signature | `[stream-end:i32 ptr:i32 num:i32] -> [i32]` |
17991805

1800-
where `read-status` is defined in WIT as:
1806+
where `copy-result` is defined in WIT as:
18011807
```wit
1802-
enum read-status {
1803-
// The operation completed and read this many elements.
1804-
complete(u32),
1805-
1806-
// The operation did not complete immediately, so callers must wait for
1807-
// the operation to complete by using `task.wait` or by returning to the
1808-
// event loop.
1809-
blocked,
1810-
1811-
// The end of the stream has been reached.
1812-
closed,
1808+
record copy-result {
1809+
progress: u32,
1810+
status: copy-status
18131811
}
1814-
```
1815-
1816-
and `write-status` is the same as `read-status` except without the optional
1817-
error on `closed`, so it is defined in WIT as:
1818-
```wit
1819-
enum write-status {
1820-
// The operation completed and wrote this many elements.
1821-
complete(u32),
18221812
1823-
// The operation did not complete immediately, so callers must wait for
1824-
// the operation to complete by using `task.wait` or by returning to the
1825-
// event loop.
1826-
blocked,
1813+
enum copy-status {
1814+
// The read/write completed successfully and is ready for more.
1815+
completed,
18271816
1828-
// The reader is no longer reading data.
1817+
// The other end closed and so there will be no more copies.
18291818
closed,
1819+
1820+
// The read/write was cancelled by {stream,future}.cancel-{read,write}.
1821+
cancelled
18301822
}
18311823
```
18321824

18331825
The `stream.read` and `stream.write` built-ins take the matching [readable or
18341826
writable end] of a stream as the first parameter and a buffer for the `T`
1835-
values to be read from or written to. The return value is either the number of
1836-
elements (possibly zero) that have been eagerly read or written, a sentinel
1837-
indicating that the operation did not complete yet (`blocked`), or a sentinel
1838-
indicating that the stream is closed (`closed`). For reads, `closed` has an
1839-
optional error context describing the error that caused to the stream to close.
1840-
1841-
In the Canonical ABI, the buffer is passed as a pointer to a buffer in linear
1842-
memory and the size in elements of the buffer. (See [`canon_stream_read`] in
1843-
the Canonical ABI explainer for details.)
1844-
1845-
`read-status` and `write-status` are lowered in the Canonical ABI as:
1846-
- The value `0xffff_ffff` represents `blocked`.
1847-
- Otherwise, if the bit `0x8000_0000` is set, the value represents `closed`.
1848-
- Otherwise, the value represents `complete` and contains the number of
1849-
element read or written.
1850-
1851-
(See [`pack_async_copy_result`] in the Canonical ABI explainer for details.)
1827+
values to be read from or written to.
1828+
1829+
If the return value is a `copy-result`, then the `progress` field indicates how
1830+
many `T` elements were read or written from the given buffer before the stream
1831+
or future reached the status indicated in the `status` field. For example, a
1832+
return value of `{progress:4, status:closed}` from a `stream<u32>.read` means
1833+
that 32 bytes were copied into the given buffer before the writer end closed
1834+
the stream. The `cancelled` case can only arise as the result of a
1835+
`{stream,future}.cancel-{read,write}` operation (defined below) and is included
1836+
in `copy-status` because the `copy-result` type is shared.
1837+
1838+
If the return value is `none`, then the operation blocked and the caller needs
1839+
to [wait](Async.md#waiting) for progress (via `waitable-set.{wait,poll}` or, if
1840+
using a `callback`, by returning to the event loop) which will asynchronously
1841+
produce an `event` containing a `copy-result`.
1842+
1843+
In the Canonical ABI, the buffer is passed as an `i32` offset into linear
1844+
memory and the `i32` size in elements of the buffer and the
1845+
`option<copy-result>` return value is bit-packed into the single `i32` return
1846+
value where:
1847+
* `0xffff_ffff` represents `none`.
1848+
* Otherwise, the `status` is in the low 4 bits and the `progress` is in the
1849+
high 28 bits.
1850+
1851+
(See [`canon_stream_read`] in the Canonical ABI explainer for details.)
18521852

18531853
###### 🔀 `future.read` and `future.write`
18541854

1855-
| Synopsis | |
1856-
| -------------------------------------------- | ------------------------------------------------------------------------------ |
1857-
| Approximate WIT signature for `future.read` | `func<T>(e: readable-future-end<T>, b: writable-buffer<T; 1>) -> read-status` |
1858-
| Approximate WIT signature for `future.write` | `func<T>(e: writable-future-end<T>, b: readable-buffer<T; 1>) -> write-status` |
1859-
| Canonical ABI signature | `[future-end:i32 ptr:i32] -> [i32]` |
1855+
| Synopsis | |
1856+
| -------------------------------------------- | ------------------------------------------------------------------------------------- |
1857+
| Approximate WIT signature for `future.read` | `func<T>(e: readable-future-end<T>, b: writable-buffer<T; 1>) -> option<copy-result>` |
1858+
| Approximate WIT signature for `future.write` | `func<T>(e: writable-future-end<T>, b: readable-buffer<T; 1>) -> option<copy-result>` |
1859+
| Canonical ABI signature | `[future-end:i32 ptr:i32] -> [i32]` |
18601860

1861-
where `read-status` and `write-status` are defined as in
1862-
[`stream.read` and `stream.write`](#-streamread-and-streamwrite).
1861+
where `copy-result` is defined as in [`stream.read` and
1862+
`stream.write`](#-streamread-and-streamwrite). The `<T; 1>` in the buffer types
1863+
indicates that these buffers may hold at most one `T` element.
18631864

18641865
The `future.{read,write}` built-ins take the matching [readable or writable
18651866
end] of a future as the first parameter, and a buffer for a single `T` value to
1866-
read into or write from. The return value is either `complete` if the future
1867-
value was eagerly read or written, a sentinel indicating that the operation did
1868-
not complete yet (`blocked`), or a sentinel indicating that the future is
1869-
closed (`closed`).
1870-
1871-
The number of elements returned when the value is `complete` is at most `1`.
1867+
read into or write from. The return value has the same meaning as with
1868+
`stream.{read,write}`, where the buffer-size has been fixed to `1`.
18721869

1873-
The `<T; 1>` in the buffer types indicates that these buffers may hold at most
1874-
one `T` element.
1875-
1876-
In the Canonical ABI, the buffer is passed as a pointer to a buffer in linear
1877-
memory. (See [`canon_future_read`] in the Canonical ABI explainer for details.)
1870+
The Canonical ABI is the same as `stream.{read,write}` except for the removal
1871+
of the `num` `i32` parameter. (See [`canon_future_read`] in the Canonical ABI
1872+
explainer for details.)
18781873

18791874
###### 🔀 `stream.cancel-read`, `stream.cancel-write`, `future.cancel-read`, and `future.cancel-write`
18801875

1881-
| Synopsis | |
1882-
| --------------------------------------------------- | ---------------------------------------------------- |
1883-
| Approximate WIT signature for `stream.cancel-read` | `func<T>(e: readable-stream-end<T>) -> read-status` |
1884-
| Approximate WIT signature for `stream.cancel-write` | `func<T>(e: writable-stream-end<T>) -> write-status` |
1885-
| Approximate WIT signature for `future.cancel-read` | `func<T>(e: readable-future-end<T>) -> read-status` |
1886-
| Approximate WIT signature for `future.cancel-write` | `func<T>(e: writable-future-end<T>) -> write-status` |
1887-
| Canonical ABI signature | `[e: i32] -> [i32]` |
1888-
1889-
where `read-status` and `write-status` are defined as in
1890-
[`stream.read` and `stream.write`](#-streamread-and-streamwrite).
1891-
1892-
The `stream.cancel-read`, `stream.cancel-write`, `future.cancel-read`, and
1893-
`future.cancel-write` built-ins take the matching [readable or writable end] of
1894-
a stream or future that has an outstanding `blocked` read or write. If
1895-
cancellation finished eagerly, the return value is `complete`, and provides the
1896-
number of elements read or written into the given buffer (`0` or `1` for a
1897-
`future`). If cancellation blocks, the return value is `blocked` and the caller
1898-
must `task.wait`. If the stream or future is closed, the return value is
1899-
`closed`.
1900-
1901-
For `future.*`, the number of elements returned when the value is `complete`
1902-
is at most `1`.
1903-
1904-
In the Canonical ABI with the `callback` option, returning to the event loop is
1905-
equivalent to a `task.wait`, and a `{STREAM,FUTURE}_{READ,WRITE}` event will be
1906-
delivered to indicate the completion of the `read` or `write`. (See
1876+
| Synopsis | |
1877+
| --------------------------------------------------- | ----------------------------------------------------------- |
1878+
| Approximate WIT signature for `stream.cancel-read` | `func<T>(e: readable-stream-end<T>) -> option<copy-result>` |
1879+
| Approximate WIT signature for `stream.cancel-write` | `func<T>(e: writable-stream-end<T>) -> option<copy-result>` |
1880+
| Approximate WIT signature for `future.cancel-read` | `func<T>(e: readable-future-end<T>) -> option<copy-result>` |
1881+
| Approximate WIT signature for `future.cancel-write` | `func<T>(e: writable-future-end<T>) -> option<copy-result>` |
1882+
| Canonical ABI signature | `[e: i32] -> [i32]` |
1883+
1884+
where `copy-result` is defined as in [`stream.read` and
1885+
`stream.write`](#-streamread-and-streamwrite).
1886+
1887+
The `{stream,future}.cancel-{read,write}` built-ins take the matching [readable
1888+
or writable end] of a stream or future that has a pending
1889+
`{stream,future}.{read,write}`.
1890+
1891+
If cancellation finishes eagerly, the return value is a `copy-result`. If
1892+
cancellation blocks, the return value is `none` and the caller must wait for a
1893+
corresponding `{stream,future}-{read,write}` event via
1894+
`waitable-set.{wait,poll}` or, when using a `callback`, returning to the event
1895+
loop. In either case, the `status` of the `copy-result` may be `cancelled` but
1896+
may also be `completed` or `closed`, if one of these racily happened first.
1897+
1898+
In the Canonical ABI, the `option<copy-result>` is bit-packed into the single
1899+
returned `i32` in the same way as `{stream,future}.{read,write}`. (See
19071900
[`canon_stream_cancel_read`] in the Canonical ABI explainer for details.)
19081901

19091902
###### 🔀 `stream.close-readable`, `stream.close-writable`, `future.close-readable`, and `future.close-writable`
@@ -2372,8 +2365,7 @@ the function has a compatible signature.
23722365
When a function is annotated with `async`, bindings generators are expected to
23732366
emit whatever asynchronous language construct is appropriate (such as an
23742367
`async` function in JS, Python or Rust). Note the absence of
2375-
`[async constructor]`. See the [async
2376-
explainer](Async.md#sync-and-async-functions) for more details.
2368+
`[async constructor]`. See the [async explainer] for more details.
23772369

23782370
The `label` production used inside `plainname` as well as the labels of
23792371
`record` and `variant` types are required to have [kebab case]. The reason for
@@ -2900,12 +2892,12 @@ For some use-case-focused, worked examples, see:
29002892
[`canon_thread_spawn_ref`]: CanonicalABI.md#-canon-threadspawn_ref
29012893
[`canon_thread_spawn_indirect`]: CanonicalABI.md#-canon-threadspawn_indirect
29022894
[`canon_thread_available_parallelism`]: CanonicalABI.md#-canon-threadavailable_parallelism
2903-
[`pack_async_copy_result`]: CanonicalABI.md#-canon-streamfuturereadwrite
29042895
[the `close` built-ins]: CanonicalABI.md#-canon-streamfutureclose-readablewritable
29052896
[Shared-Nothing]: ../high-level/Choices.md
29062897
[Use Cases]: ../high-level/UseCases.md
29072898
[Host Embeddings]: ../high-level/UseCases.md#hosts-embedding-components
29082899

2900+
[Async Explainer]: Async.md
29092901
[Task]: Async.md#task
29102902
[Current Task]: Async.md#current-task
29112903
[Context-Local Storage]: Async.md#context-local-storage

0 commit comments

Comments
 (0)