@@ -132,33 +132,41 @@ Thus, backpressure combined with the partitioning of low-level state provided
132
132
by the Component Model enables sync and async code to interoperate while
133
133
preserving the expectations of both.
134
134
135
- In addition to being able to define and call whole functions asynchronously,
136
- the ` stream ` and ` future ` types can be used in function signatures to pass
137
- parameters and results incrementally over time, achieving finer-grained
138
- concurrency. Streams and futures are thus not defined to be free-standing
139
- resources with their own internal memory buffers (like a traditional channel or
140
- pipe) but, rather, more-primitive control-flow mechanisms that synchronize the
141
- incremental passing of parameters and results during cross-component calls.
142
- Higher-level resources like channels and pipes could then be defined in terms
143
- of these lower-level ` stream ` and ` future ` primitives, e.g.:
144
-
135
+ Lastly, WIT is extended with two new type constructors—` future<T> ` and
136
+ ` stream<T> ` —to allow new WIT interfaces to explicitly represent concurrency in
137
+ * both* the sync and async ABIs in way that can be bound to many language's
138
+ idiomatic futures, promises, streams and channels. Futures and streams are,
139
+ semantically, unidirectional unbuffered channels with a dynamically-enforced
140
+ [ session type] describing the passing of exactly 1 or 0..N values, resp., with
141
+ the additional ability for the reader end to signal a loss of interest
142
+ to the writer end. Thus, futures and streams are more primitive concepts than,
143
+ e.g., Unix pipes (which have an associated intermediate memory buffer that
144
+ values are copied into and out of). Rather, streams could be used to * define*
145
+ higher-level concepts like pipes, HTTP response bodies or stream transformers.
146
+ E.g.:
145
147
``` wit
146
148
resource pipe {
147
- constructor(buffer-size: u32);
148
- write: func(bytes: stream<u8>) -> result;
149
- read: func() -> stream<u8>;
149
+ constructor(buffer-size: u32);
150
+ write: func(bytes: stream<u8>) -> result;
151
+ read: func() -> stream<u8>;
152
+ }
153
+ resource response {
154
+ constructor(body: stream<u8>);
155
+ consume-body: func() -> stream<u8>;
150
156
}
157
+ transform: func(in: stream<point>) -> stream<point>;
151
158
```
152
-
153
- but also many other domain-specific concurrent resources like WASI HTTP request
154
- and response bodies or WASI blobs. Streams and futures are however high-level
155
- enough to be bound automatically to many source languages' built-in concurrency
156
- features like futures, promises, streams, generators and iterators, unlike
157
- lower-level concurrency primitives (like callbacks or ` wasi:io@0.2.0 `
158
- ` pollable ` s). Thus, the Component Model seeks to provide the lowest-level
159
- fine-grained concurrency primitives that are high-level and idiomatic enough to
160
- enable automatic generation of usable language-integrated bindings.
161
-
159
+ A ` future ` or ` stream ` in a function signature always refers to the transfer of
160
+ unique ownership of the * readable end* of the future or stream. To get a
161
+ * writable end* , a component must first internally create a (readable, writable)
162
+ end pair (via the [ ` {stream,future}.new ` ] built-ins) and then pass the readable
163
+ end elsewhere (e.g., in the above WIT, as a parameter to an imported
164
+ ` pipe.write ` or as a result of an exported ` transform ` ). Given the readable or
165
+ writable end of a future or stream (represented as an ` i32 ` index into the
166
+ component instance's handle table), Core WebAssembly can then call a
167
+ [ ` {stream,future}.{read,write} ` ] built-in to synchronously or asynchronously
168
+ copy into or out of a caller-provided buffer of Core WebAssembly linear (or,
169
+ soon, GC) memory.
162
170
163
171
## Concepts
164
172
@@ -1124,6 +1132,7 @@ comes after:
1124
1132
[ CPS Transform ] : https://en.wikipedia.org/wiki/Continuation-passing_style
1125
1133
[ Event Loop ] : https://en.wikipedia.org/wiki/Event_loop
1126
1134
[ Structured Concurrency ] : https://en.wikipedia.org/wiki/Structured_concurrency
1135
+ [ Session Types ] : https://en.wikipedia.org/wiki/Session_type
1127
1136
[ Unit ] : https://en.wikipedia.org/wiki/Unit_type
1128
1137
[ Thread-local Storage ] : https://en.wikipedia.org/wiki/Thread-local_storage
1129
1138
[ FS or GS Segment Base Address ] : https://docs.kernel.org/arch/x86/x86_64/fsgs.html
@@ -1144,6 +1153,8 @@ comes after:
1144
1153
[ `waitable-set.wait` ] : Explainer.md#-waitable-setwait
1145
1154
[ `waitable-set.poll` ] : Explainer.md#-waitable-setpoll
1146
1155
[ `thread.spawn*` ] : Explainer.md#-threadspawn_ref
1156
+ [ `{stream,future}.new` ] : Explainer.md#-streamnew-and-futurenew
1157
+ [ `{stream,future}.{read,write}` ] : Explainer.md#-streamread-and-streamwrite
1147
1158
[ ESM-integration ] : Explainer.md#ESM-integration
1148
1159
1149
1160
[ Canonical ABI Explainer ] : CanonicalABI.md
0 commit comments