- `fn name` names a top-level function as a value (E_FNREF, lowers to @fn_<name>); the worker entry point for Job.parallel_for, which checks it takes (int, pointer-like) and returns void. - runtime/native/threads.ll (pthreads) and threads_win.ll (Win32 SRWLOCK/CONDITION_VARIABLE): a pool of one worker per core but one, parked between batches; every thread claims chunks by compare-and-swap. Linked only into programs that use Job/Promise/Sync, by `ludicc -o`, `ludic build` and the test suite's build helper. - Sync.* is real: native mutexes, atomics as cmpxchg retry loops (neither clang takes atomicrw, the PC's rejects seq_consistent), mutex-guarded channels, Sync.cpu_count from the OS. - spawn/despawn on a pool thread stop the program with a located panic. - examples/library/threads.ludic and its test; docs for fn, Job.parallel_for, Job.is_worker. - Reseeded (bootstrap-cfree: out.ll == seed.ll). 141/141 on macOS; jobs, threads and the guard pass on Windows from the reseeded Windows seed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
13 lines
868 B
Markdown
13 lines
868 B
Markdown
bump: minor
|
|
type: feat
|
|
**Real OS threads behind `Job.*` and `Sync.*`** — `Job.parallel_for` runs work across every core.
|
|
|
|
- **`fn name`** — an expression naming a top-level function as a value, for a worker's entry point.
|
|
No closures: the data a worker needs is passed in.
|
|
- **`Job.parallel_for(count, fn work, ctx)`** — `work(i, ctx)` for every `i` in `[0, count)`, split
|
|
into chunks across a worker pool (one thread per core but one, pthreads or Win32) and the calling
|
|
thread; returns when all are done. `Job.is_worker()` says whether code is on a pool thread.
|
|
- **`Sync.*` is thread-safe** — mutexes are real mutexes, atomics are compare-and-swap, channels are
|
|
guarded, and `Sync.cpu_count()` reports the machine's cores.
|
|
- **A worker must not change the world** — `spawn` and `despawn` on a pool thread stop the program with
|
|
a located message.
|