/
nv-lang
/
nova
Обзор
Документация
Войти
/
nv-lang
/
nova
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
std/src/runtime/runtime.nv
181 строка
8 KB
Evgeniy Golovin
merge: comment-hygiene-2 — чистка комментариев std (batch 1-20) + линт-свип 330→13
01 авг 2026, 18:13
01 авг 2026, 18:13
bb8b33d
Код
Авторство
О чём код?
// std/runtime/runtime.nv — M:N runtime control API. // // M:N-рантайм Nova — production-grade: work-stealing scheduler, // preemption, per-worker libuv loop, hardened channels, fiber arena. // Сейчас он **opt-in**: параллелизм включается вызовом `runtime.init`. // // Инфраструктура для default-on подготовлена (`nova_runtime_auto_arm()` API // + auto-arm в `nova_runtime_spawn_global` / `nova_runtime_spawn_into`), // но не активирована: codegen-emit в main() пока не вызывает auto-arm — // полный флип упирается в pre-existing M:N баги в supervised-drain / // sleep-wake / per-fiber handlers, которые до этого проявлялись // только под explicit `runtime.init` и требуют отдельной серии // фиксов. См. followup-секцию `simplifications.md`. // // **NOT auto-gen.** Hand-maintained namespace `runtime.*` — c-имя // (`nova_runtime_*` / `nova_fiber_yield` для `yield`) приходит через // `ExternalRegistry::NAMESPACE_OVERRIDES` (compiler-codegen/src/codegen/ // external_registry.rs); этот файл — embedded builtin source, единственный // source of truth и для checker'а, и для codegen. // // Число worker-потоков (порядок разрешения): // explicit runtime.init(n>0) > ENV NOVA_MAXPROCS > auto-detect // (uv_available_parallelism — cgroup+affinity-aware). // Клэмп [1, 1024]. `NOVA_MAXPROCS` — аналог `GOMAXPROCS`; невалидное // значение → диагностика + fallback на auto-detect. // // API: // runtime.init(n) // ARM рантайм (0 = auto/NOVA_MAXPROCS) // runtime.shutdown() // graceful join всех worker'ов // runtime.maxprocs() // целевое число worker'ов (резолвится и до init) // runtime.worker_count() // фактически поднятые worker'ы (0 до первого spawn) // runtime.is_initialized() // bool — M:N запрошен (runtime.init вызван)? // runtime.current_worker_id() // id worker'а (-1 = main thread) // runtime.yield() // кооперативный yield // // **Lazy worker-пул:** `runtime.init` НЕ создаёт // потоки сразу — лишь ARM'ит рантайм и фиксирует целевое число. // Worker-потоки + sysmon материализуются лениво на первом `spawn`. // Программа без `spawn` идёт на одном главном потоке. `runtime.init` — // **одноразовый тюнер**: до первого spawn повторный вызов валидно // переопределяет цель; после материализации пула — диагностируемый // no-op на stderr. `runtime.shutdown()` останавливает пул; после него // `runtime.init` снова валиден. module runtime.runtime // ─── runtime namespace ────────────────────────────────────────── /// An M:N runtime with a target number of `n` worker threads. /// /// `n = 0` → auto-detect (`NOVA_MAXPROCS` / `uv_available_parallelism()`). /// /// **Lazy (Plan 83.1 Ф.4, D137):** `init` does NOT create worker threads — it only /// fixes the target number. The pool materializes on the first `spawn`. Until /// the first spawn a repeated `init` validly redefines the target; after /// materialization `init` is a diagnosed no-op on stderr. /// /// Each worker (after materialization) has: /// - its own libuv event loop; /// - its own fiber scope (worker-local push queue); /// - its own fiber arena (Plan 44.2 Linux/macOS — lazily init per thread). /// /// # Effects /// /// By itself does not spawn threads — the pool comes up on the first `spawn`. /// /// # See Also /// /// - `[runtime.shutdown]` — stop the workers /// - `[runtime.maxprocs]` — target number of workers /// - `[runtime.worker_count]` — workers actually raised #stable(since = "0.1") export extern "nova" fn runtime.init(n int) -> () /// Graceful shutdown M:N runtime. /// /// Signal stop → join workers → free resources. After shutdown a repeated /// `[runtime.init]` starts new workers. /// /// **Plan 83.1 Ф.4:** called automatically on process exit /// (via `atexit` — normal return from main and `exit()`). Explicit /// calls are optional; idempotent. /// /// # Effects /// /// Blocks until all worker threads have finished. /// /// # See Also /// /// - `[runtime.init]` — start the runtime /// - `[runtime.is_initialized]` — check the state #stable(since = "0.1") export extern "nova" fn runtime.shutdown() -> () /// Number of currently running worker threads. /// /// Returns `0` if the runtime is not initialized. /// /// # See Also /// /// - `[runtime.init]` — start the runtime /// - `[runtime.maxprocs]` — the target (not actual) number of workers /// - `[runtime.is_initialized]` — bool check #stable(since = "0.1") export extern "nova" fn runtime.worker_count() -> int /// Target number of worker threads (analogous to Go `runtime.GOMAXPROCS(-1)`). /// /// Differs from `[runtime.worker_count]`: `maxprocs()` — the **target** /// (resolved from `NOVA_MAXPROCS` / auto-detect even before `runtime.init`), /// `worker_count()` — the threads actually raised. /// /// Resolution order: explicit `runtime.init(n)` > ENV `NOVA_MAXPROCS` /// > `uv_available_parallelism()`. The result is always in the range [1, 1024]. /// /// # See Also /// /// - `[runtime.worker_count]` — the workers actually raised /// - `[runtime.init]` — start the runtime #stable(since = "0.1") export extern "nova" fn runtime.maxprocs() -> int /// Check whether the M:N runtime is active. /// /// Used for conditional code paths in tests, branched on /// single-thread vs M:N behavior. /// /// # See Also /// /// - `[runtime.init]` — start the runtime /// - `[runtime.worker_count]` — number of workers #stable(since = "0.1") export extern "nova" fn runtime.is_initialized() -> bool /// Current worker ID (0..n_workers-1). /// /// Returns `-1` if called from the main thread (not from a worker fiber). /// Useful for diagnostics — which worker the fiber is running on. /// /// # See Also /// /// - `[runtime.worker_count]` — total number of workers #stable(since = "0.1") export extern "nova" fn runtime.current_worker_id() -> int /// Drain orphan fiber pool synchronously. /// /// `detach { body }` under D50 — a fire-and-forget primitive. Orphan fibers /// run in the global orphan-scope (bootstrap cooperative) or the worker /// pool (armed M:N). Drain forces synchronous completion of all pending /// orphans — analogous to Go `sync.WaitGroup.Wait()` for anonymous spawns. /// /// Used: /// - In test suites for explicit sync between `detach { side_effect }` and /// a subsequent assert. Alternative — channel-based sync. /// - On graceful shutdown (atexit registers an automatic drain — but /// the user can call it earlier, e.g. after batch detaches). /// /// Idempotent: empty orphan pool — no-op (fast return). /// /// # See Also /// /// - `detach { body }` — D50 fire-and-forget spawn primitive. /// - `[supervised]` — structured-concurrency alternative with automatic join. #stable(since = "0.1") export extern "nova" fn runtime.drain_orphans() -> () /// Cooperative yield — suspend the current fiber, let others run. /// /// In single-thread mode: equivalent to resuming the scheduler. /// In M:N mode: the fiber is placed into the worker's deque; any worker can /// pick it up next (work-stealing). /// /// Outside fiber context: no-op. Checks `cancel_requested` before yield. /// Useful for CPU-bound loops so as not to starve other fibers on the same worker. /// /// # Effects /// /// Performs a cooperative context switch. #stable(since = "0.1") export extern "nova" fn runtime.yield() -> ()