diff --git a/examples/1805-concurrency-io-blocking-async.sx b/examples/1805-concurrency-io-blocking-async.sx new file mode 100644 index 00000000..9bc722bd --- /dev/null +++ b/examples/1805-concurrency-io-blocking-async.sx @@ -0,0 +1,35 @@ +// Stream B1 (fibers) — the `Io` capability + the blocking-`Io` default +// (step B1.2). `Io` is threaded on `Context` exactly like `Allocator`: a +// `protocol #inline` at a fixed field, whose process-wide default is a +// stateless `CBlockingIo` (the mirror of `CAllocator`). +// +// In the blocking M:1 model there is no scheduler and no suspension: +// `async(worker, ..args)` runs the worker to COMPLETION synchronously, so +// the returned `Future` is born `.ready` and `await` yields the stored +// result immediately. This locks the B1.2 surface — `context.io.async(...)` +// with a lambda worker (annotated params) + `f.await()`. +// +// Worker form: a lambda `(a: i64, b: i64) -> i64 => ...` whose params are +// annotated. Named-fn workers need a `::` callable-param feature that does +// not exist yet and are DEFERRED. +#import "modules/std.sx"; + +main :: () -> i32 { + // Single-arg lambda worker. + f1 := context.io.async((n: i64) -> i64 => n * 2, 21); + v1, e1 := f1.await(); + if !e1 { print("double: {}\n", v1); } // → 42 + + // Two-arg lambda worker — exercises the `..$args` variadic forward. + f2 := context.io.async((a: i64, b: i64) -> i64 => a + b, 40, 2); + v2, e2 := f2.await(); + if !e2 { print("sum: {}\n", v2); } // → 42 + + // `now_ms` is a protocol method (a deterministic-sim Io [B1.4] can + // override it); the blocking Io returns a real monotonic clock, so we + // only assert it is non-negative, not an exact value. + t := context.io.now_ms(); + if t >= 0 { print("clock ok\n"); } + + return 0; +} diff --git a/examples/expected/1805-concurrency-io-blocking-async.exit b/examples/expected/1805-concurrency-io-blocking-async.exit new file mode 100644 index 00000000..e69de29b