Files
sx/examples/concurrency/1804-concurrency-context-snapshot.sx
agra 66bdc70bf1 test: group examples into per-category folders
Move examples/*.sx and their expected/ snapshots into per-category
subfolders (examples/<category>/...). Folder = leading filename token,
with ffi-objc/ffi-jni kept whole; filenames are unchanged. The corpus
runner and LSP sweep now discover each category's expected/ dir, while
issues/ stays flat. Example 1058's repo-root-relative companion import
is made file-relative. Path strings embedded in 164 snapshots were
regenerated (path-only changes). Test-layout docs in CLAUDE.md updated.
2026-06-21 14:41:34 +03:00

49 lines
2.2 KiB
Plaintext

// Stream B1 (fibers) step B1.1 — per-fiber `context` root, via plain
// snapshot + `push` (NO compiler change — the substrate the fiber spawn relies on).
//
// `context` is an implicit `*Context` parameter (slot 0) threaded through every
// sx call, and `push Context` allocates the new context on the caller's stack
// frame — so a function's context is CALL-CARRIED and rides its own stack, never
// read from a global. That is exactly what a fiber needs: each fiber, on its own
// stack, reads its own root context.
//
// This locks the spawn convention end-to-end with ordinary language features:
// 1. capture the spawner's context as a value (`snap := context`)
// 2. store the snapshot in a struct (the stand-in `Fiber`)
// 3. a trampoline, running under a DIFFERENT ambient context, installs the
// fiber's stored root before entering the body (`push f.root { … }`)
// The body sees the snapshot (42), not the trampoline's ambient context (99),
// and the `push` scope restores the ambient context on exit. No fiber runtime
// exists yet (that is B1.3) — this proves the context plumbing it will build on.
#import "modules/std.sx";
// Stand-in for a Fiber: stores the spawner's snapshotted root Context.
Fiber :: struct { root: Context; }
// Reads this call's context sentinel (carried in `context.data` here for the
// test; a real fiber carries its allocator / io the same way).
sentinel :: () -> i64 { return xx context.data; }
// Trampoline: runs under its own ambient context, but installs the fiber's
// stored root before entering the fiber body.
run_fiber :: (f: *Fiber) -> i64 {
push f.root {
return sentinel();
}
}
main :: () {
snap := context;
snap.data = xx 42; // the spawner's sentinel
f := Fiber.{ root = snap }; // snapshot stored in the fiber
other := context;
other.data = xx 99; // a DIFFERENT ambient context
push other {
// Ambient is 99 here; the trampoline must install f.root (42).
print("fiber root: {}\n", run_fiber(@f));
// After run_fiber returns, this scope's ambient context is intact.
print("ambient after: {}\n", sentinel());
}
}