@@ -132,33 +132,41 @@ Thus, backpressure combined with the partitioning of low-level state provided
132132by the Component Model enables sync and async code to interoperate while
133133preserving the expectations of both.
134134
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.:
145147``` wit
146148resource 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>;
150156}
157+ transform: func(in: stream<point>) -> stream<point>;
151158```
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.
162170
163171## Concepts
164172
@@ -1124,6 +1132,7 @@ comes after:
11241132[ CPS Transform ] : https://en.wikipedia.org/wiki/Continuation-passing_style
11251133[ Event Loop ] : https://en.wikipedia.org/wiki/Event_loop
11261134[ Structured Concurrency ] : https://en.wikipedia.org/wiki/Structured_concurrency
1135+ [ Session Types ] : https://en.wikipedia.org/wiki/Session_type
11271136[ Unit ] : https://en.wikipedia.org/wiki/Unit_type
11281137[ Thread-local Storage ] : https://en.wikipedia.org/wiki/Thread-local_storage
11291138[ FS or GS Segment Base Address ] : https://docs.kernel.org/arch/x86/x86_64/fsgs.html
@@ -1144,6 +1153,8 @@ comes after:
11441153[ `waitable-set.wait` ] : Explainer.md#-waitable-setwait
11451154[ `waitable-set.poll` ] : Explainer.md#-waitable-setpoll
11461155[ `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
11471158[ ESM-integration ] : Explainer.md#ESM-integration
11481159
11491160[ Canonical ABI Explainer ] : CanonicalABI.md
0 commit comments