[M1-SYS-01] System registry - #24
Merged
Merged
Conversation
Roadmap step M1-SYS-01 (roadmap/M1-heartbeat.md), scope only. System registry (FR-1.3: plain registered functions with declared time budgets and declared component I/O): Public header src/laige-sim/include/laige/sim/system.h: - SystemId: 32-bit dense id assigned in registration order (0 reserved, per-world, deterministic - component.h id contract). - SystemDef: name + run (SystemFn = void(*)(World&, SystemContext&)) + budgetMs in ms (fpx16_16, exact - ADR 0002; the future sim source scan stays float-free). - LAIGE_SYSTEM(Name, budget_ms): namespace-scope macro declaring the plain system function and building the def (Name##Def) - no class, no inheritance (FR-1.3). - SystemContext: the per-tick view of the world; each<T1..TN>(fn, Read/Write tags...) delegates to World::each (query.h; the definition lives in entity.h where World is complete). - Io<T, Access>: the per-component declared I/O tag for World::registerSystem; the I/O is a set, not a multiset (disjoint read/write id sets in the world's record; ascending-id enumeration order documented). - SystemInfo: the registered system's snapshot (def copy + declaresRead/declaresWrite), the M1-SYS-02/M1-PROF-01 feed. - detail::SystemRecord + the IsIoTag/IsIoComponent/IoComponent traits (class form - the api scanner parses class partial specializations; variable templates are an unsupported scanner construct). World API (entity.h, the World home): registerSystem(def, Io<...>...) (header-defined template), systemCount(), system(id) (systems.cpp). The fixed kMaxSystems (256) record table is allocated in create() like the component registry; the registry travels with the world on move and survives clear(). Validation (first failure wins; every failure is one rate-limited structured warn + Status - FR-12.3, LOG-004): moved-from world -> InvalidArgument (no warn, like registerComponent); null/empty name -> system/name_invalid; null run -> system/run_invalid; budget <= 0 -> system/budget_invalid (the budget must be explicit and positive); duplicate name -> system/duplicate (the roadmap's named property); Io T not a component -> compile error (static_assert); Io T not registered in this world -> system/io_unregistered; same component declared twice (any access) -> system/io_duplicate; > kMaxSystems -> BudgetExhausted + system/budget_exhausted. The def is value-copied into the record table: no allocation at registration (setup path). Tests: new SystemRegistry suite (ctest -R system_registry; 25 tests) - registration, ids, the def value copy, the I/O sets + zero-I/O pack, context delegation (write + read paths through the plain functions), every validation error, the kMaxSystems budget (257 distinct names), system() id validation, id stability across two worlds (ARCH-010), registration-order-determines-ids, move/clear/moved-from-world lifetime, the zero-alloc registration window (operator-new counter, non-sanitizer trees), and the warn-once + rate_limited-sink checks (system/duplicate fields, system/budget_invalid budget_raw field). Docs (CORE-006/DOC-007): docs/api/system_registry.md (full contract + Performance section) linked from docs/README.md; src/laige-sim/ README status updated (including the M1-ECS-06/07 lines); entity.h preamble + World member docs carry the M1-SYS-01 note; laige-api.json regenerated (489 symbols; api-real-tree green). Verify (local): - ctest -R system_registry green on build (25/25, incl. the zero-alloc window), full suite 41/41 on build. - Full suite 41/41 on build-asan (leak-free), build-tsan, build-clang, build-release, build-shared; zero new warnings under NFR-8.10 on every tree. - laige-api regenerated + api-real-tree/api fixture tests green; tools/laige-include-lint OK (27 source files, 1/10 vendored deps).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Roadmap step M1-SYS-01 (system registry,
roadmap/M1-heartbeat.md), scope only.What
Plain registered system functions (FR-1.3: no class, no inheritance) with declared time budgets and declared component I/O:
src/laige-sim/include/laige/sim/system.h(new):SystemId— dense 32-bit ids from 1, registration order, per-world, deterministic (ARCH-010, theComponentTypeIdprecedent);SystemDef— name +SystemFn(void (*)(World&, SystemContext&)) +budgetMsin milliseconds asfpx16_16(exact, ADR 0002 — keeps the future M1-DET-01 source scan float-free);LAIGE_SYSTEM(Name, budget_ms)— namespace-scope macro: the function declaration + theName##Defdef variable (the PRD Appendix B shape);SystemContext— the per-tick world view;each<T1..TN>(fn, Read/Write tags...)delegates toWorld::each(definition out-of-line inentity.hwhereWorldis complete);Io<T, Access>— the per-component declared I/O tag; a component appears at most once per system (a set, not a multiset) — M1-SYS-02's conflict checks consume the disjoint read/write sets;SystemInfo— the snapshot the scheduler/profiler pull (declaresRead/declaresWrite);kMaxSystems = 256(engine-level bound, CORE-005).World::registerSystem(def, Io<...>...),World::systemCount(),World::system(id)— the World home inentity.h+systems.cpp; the fixed record table is allocated increate()(setup path, like the component registry); the registry travels with the world on move and survivesclear().Validation (normative order — first failure wins)
InvalidArgument(no warn, the registerComponent precedent)InvalidArgument+ warnsystem/name_invalidInvalidArgument+ warnsystem/run_invalidInvalidArgument+ warn (the budget must be explicit)system/budget_invalidInvalidArgument+ warnsystem/duplicateIo<T>:Tunregistered in this worldInvalidArgument+ warnsystem/io_unregisteredInvalidArgument+ warnsystem/io_duplicatekMaxSystemssystemsBudgetExhausted+ warnsystem/budget_exhaustedA non-component
TinIo<T, ...>is a compile error (static_assert). Every warn is rate-limited (LOG-004), subsystemsystem, with stable fields (name,budget_raw,existing_system_id,component_id,systems).Tests
New
SystemRegistrysuite — 25 tests, CTest entrysystem_registry(also in the TSan property list): registration, dense ids, the def value copy, the I/O sets + zero-I/O pack, context delegation (write + read paths through the plain functions), every validation error, the 257-system budget,system()id validation, id stability across two worlds (ARCH-010), move/clear/moved-from-world lifetime, the zero-alloc registration window (test-only operator-new counter, non-sanitizer trees), and the warn-once +rate_limitedsink checks.Verify (local)
ctest -R system_registrygreen (25/25, incl. the zero-alloc window); full suite 41/41 onbuild.build-asan(leak-free),build-tsan,build-clang,build-release,build-shared; zero new warnings under NFR-8.10.laige-api.jsonregenerated (489 symbols);api-real-tree+ the api fixture tests green.tools/laige-include-lintOK (27 source files, 1/10 vendored deps).Docs (CORE-006)
docs/api/system_registry.md(full contract + Performance section), linked fromdocs/README.md;src/laige-sim/README.mdstatus updated (incl. the M1-ECS-06/07 lines);Notes
SystemDefcarries the declared I/O at registration, not in the def: component ids are per-world runtime values and cannot be baked into the compile-time def (documented in the header).IsIoTag/IsIoComponent): the api scanner parses class template partial specializations; variable templates are an unsupported scanner construct (avoided rather than extending the scanner in this step).LAIGE_SYSTEMexpansion ends in;: the call site (per the PRD sketch) carries no trailing semicolon.