Type erased C++ API and related code#251
Conversation
…fixes invalid [[nodiscard]], range temporary lifetimes, map-vs-set iteration, and missing fallback return
Code Review — PR #251: Type-erased C++ API
OverviewThis is a substantial architectural rework of the C++ runtime layer. The core idea is a shift from virtual dispatch + deep builder hierarchies to a struct-of-function-pointers (ops-table) type-erasure pattern, combined with compile-time reflection via The design direction is sound. The rest of this review covers specific concerns worth addressing before the PR is marked ready. Architecture & DesignStrengths
Concerns
Specific Issues1. Committed build artifacts — blocker
2.
|
| Area | Status |
|---|---|
tagged_ptr.h discriminated pointer |
No dedicated tests |
BoundaryBindingPlan bind/unbind/rebind paths |
No tests |
ActiveTrie evict-to-pending path |
Unclear from PR |
TSInput/TSOutput lifecycle in isolation |
No tests (only graph-level) |
test_tracked_set.py (deleted) |
Not replaced |
test_memory_size.py (deleted) |
Not replaced |
The new conftest.py auto-skip for HGRAPH_USE_CPP=0 is a good addition — it prevents false failures in pure-Python environments.
Performance
- The ops-table pattern correctly avoids vtable-per-instance overhead.
arg_provider<T>specializations withstd::make_index_sequenceexpansion ininvoke<Fn>()should compile down to a single inline call site — good.ActiveTrieusesstd::unordered_map<size_t, std::unique_ptr<ActiveTrieNode>>for children. For small fan-outs (typical in TSB), a small flat array orabsl::flat_hash_mapmight reduce allocation pressure. Not urgent, but worth noting for later.- The
state_trace.jsonremoval is a significant improvement to clone/checkout times.
Minor / Nits
- Several design RFCs in
docs/design/use future tense ("will be implemented"). Once the work they describe lands, these should be updated or flagged as historical. A naming convention likedocs/design/rfc/vsdocs/design/decisions/might help. static_schema.handstatic_signature.hare each over 1000 lines. Both are compile-time-only headers with dense template machinery. Consider factoring out thefixed_stringutilities into a separatecpp/include/hgraph/util/fixed_string.hto keep the schema headers focused.
Summary
The architecture is moving in the right direction and the scale of cleanup is impressive. The main blockers before marking ready are:
- Remove
cpp/tests/asan-build/from version control. - Fill the
tagged_ptr,BoundaryBinding, and deleted-test coverage gaps (or explicitly track them as follow-up issues). - Resolve or track the
ConstNodePython round-trip TODO.
The __class__ mutation and alarm-scheduling smell are medium-priority and can reasonably land as tracked issues rather than blocking the PR.
Code Review — PR #251: Type-Erased C++ API
OverviewThis is a substantial architectural rewrite of the hgraph C++ backend, introducing a complete type-erased value and time-series type system. The core ideas are sound:
The separation of "what a type is" ( Code Quality & Strengths
Issues & Suggestions1. Potential TOCTOU Race in
|
| Area | Assessment |
|---|---|
| Architecture | Sound — clean separation of schema vs behavior |
| API Safety | Some rough edges (const_cast, raw char*, public TypeMeta fields) |
| Thread Safety | Documented but TOCTOU race in scalar_type_meta<T>() |
| Documentation | Strong — good Doxygen coverage |
| Test Coverage | Good behavioral tests; C++ unit tests for core value layer would add depth |
| Build | Well-structured with good sanitizer support |
Main asks before merging:
- Resolve the
scalar_type_meta<T>()thread safety issue - Fix
const_castinregister_type(name) - Address the
nb::objectstatic sentinel lifetime risk - Mark or enforce
TypeMetaimmutability after registry registration
Happy to dig deeper into any specific area.
Code Review: Type-Erased C++ API (PR #251)This is a substantial PR introducing the new type-erased C++ API. Given the stated WIP status, this review focuses on issues that should be addressed before or around merge rather than minor style nits. Overall the architecture is well-conceived — the dispatch-caching approach, RAII mutation scopes, and compile-time reflection system are all solid design choices. Critical / Must Fix1. Use-after-free in
2. Unsafe void reinterpret_cast without runtime validation (atomic.h ~line 115)* [[nodiscard]] static AtomicState<T> *state(void *data) noexcept {
return std::launder(reinterpret_cast<AtomicState<T> *>(data));
}There is no check that High Severity3. Thread-safety holes in The 4. The Python type-var context is mutated during signature export. If any future code path exports signatures concurrently, this is a data race. Worth a comment at minimum; worth a thread-local or mutex if export is ever done outside the GIL. 5. GIL deadlock in [](PyObject *o) noexcept {
nb::gil_scoped_acquire guard; // deadlocks if GIL already held
Py_INCREF(o);
}
Medium Severity6. Hash collision risk in h ^= std::hash<int64_t>{}(k.range) << 2;
h ^= std::hash<int64_t>{}(k.min_range) << 3;XOR with small constant shifts means auto hash_combine = [](size_t h, size_t v) { return h ^ (v + 0x9e3779b9 + (h << 6) + (h >> 2)); };7. Incomplete exception translator (_hgraph_module.cpp ~lines 34-56) Only 8. Python module re-import on every call (static_signature.h ~line 612)
static nb::module_ mod = nb::module_::import_("hgraph");9. Python type generation not cached (static_schema.h ~lines 723-738)
Build System10. Header files passed as source files to
11. Deprecated These set global scope and leak into downstream targets. Replace with: target_include_directories(${PROJECT_NAME} PRIVATE ...)
target_compile_definitions(${PROJECT_NAME} PRIVATE hgraph_EXPORTS)12. macOS deployment target defaults to 15.0 (CMakeLists.txt ~line 72) This will silently break CI on any macOS runner < 15. Defaulting to 13.0 or 12.0 is safer and still allows Test Coverage GapsThe new
Suggested location per CLAUDE.md conventions: Minor
Summary
Given the WIP notice, most of these are expected to be addressed before merge. The architecture underneath is strong — the type-erasure dispatch model, the RAII mutation scopes, and the compile-time reflection system are all good design choices. The main things I'd want resolved before merge are the |
Code Review: Type-erased C++ API (PR #251)This is a substantial architectural PR introducing a type-erased C++ API for the hgraph core runtime. Given the WIP label and the scale of the change (~67k additions, ~186k deletions, 399 files), this review focuses on the most important design and quality concerns. OverviewThe PR introduces several key components:
The architectural direction is sound: separating schema/dispatch from data, using pointer-tagging for zero-overhead discrimination, and the trie for sparse active-state tracking are all good choices for a performance-sensitive reactive engine. Strengths
Issues and Suggestions1.
|
Code Review: Type-Erased C++ API (PR #251)
OverviewThis is a significant architectural refactor that replaces the previous C++ API with a type-erased design using Scale: +67,226 / −186,416 lines across 300+ files. A large portion of the deletions appear to be the removal of old per-type builder headers (all of Architecture — What Works Well
Issues and Suggestions1. Missing file referenced in CMakeLists.txt
# CMakeLists.txt lists:
include/hgraph/types/base_time_series.h # ← file not on diskAction: Either create the file (even as a stub with 2. TODO in
|
| Category | Assessment |
|---|---|
| Architecture | Sound type-erasure design; consistent pattern across types |
| Correctness | Missing file in CMakeLists, TODO alarm API misplacement need resolution |
| Safety | BuiltNodeSpec GIL/Python entanglement is a latent risk |
| Build | Release build debug symbols should be opt-in |
| Tests | Needs verification that existing suite passes |
This is a solid foundation for the new C++ API. The main blockers before marking it ready are: (1) resolving the base_time_series.h missing file, (2) addressing the set_alarm/cancel_alarm misplacement, and (3) confirming the test suite passes. The Python object mixing in BuiltNodeSpec is worth a design discussion but may be acceptable as an intentional bridge.
Signed-off-by: Alexander Balabin <abalabin@bamfunds.com>
…orary retain view object while in use
Code Review: Type Erased C++ API and Related CodeNote: This review is based on reading the files present in the working tree, which correspond to the PR branch. The PR is explicitly marked WIP, so feedback focuses on design-level concerns, specific bugs, and patterns worth addressing before merge. OverviewThis is a large architectural rewrite (~67k additions, ~186k deletions) introducing a type-erased C++ API for the hgraph engine. The core idea — separating schema identity ( Strengths
Issues and Suggestions1.
|
Signed-off-by: Alexander Balabin <abalabin@bamfunds.com>
…orary some distilled failing tests and a little bit of fixes
|
Code Review: Type-erased C++ API and related code
OverviewThis is a substantial and well-motivated refactoring (~67K additions, ~186K deletions). The core idea — replacing the old Python-wrapper-centric C++ layer with a proper type-erased C++ API using ops-table dispatch — is the right architectural direction. The key new types are:
Positive aspects
Issues to address before mergeDesign / Correctness1. Alarm methods in 2. 3. Unchecked 4. 5. Performance6. 7. 8. 9. Minor / Style10. 11. 12. Test coverageThe existing
Given the WIP status this is expected — flagging for pre-merge completeness. SummaryThe type-erased ops-table design is sound and a clear improvement over the previous Python-wrapper layer. The The main items to resolve before merge are: the alarm method placement (issue 1), the potential Python object leak on shutdown (issue 2), and the raw owning pointer from |
Code Review: Type Erased C++ API
OverviewThis PR is a significant architectural rework of the C++ runtime. It replaces the previous inheritance-heavy, pybind11-coupled API with a clean type-erasure via explicit vtables approach. The core design:
The ~25-file Code Quality & StyleStrengths:
Style observations:
Potential Bugs & Issues
Architecture / Code SmellAcknowledged alarm placement (
Heavy header chain from Performance
Test CoverageExisting tests in
SecurityNo concerns. GIL acquisition in SummaryThis is a well-considered design. The type-erasure + stateless-hook pattern achieves the stated goals of readability and debuggability. The main items to address before merging:
Looking forward to this landing — it's a meaningful step forward for the C++ runtime. |



This is hopefully the last attempt to create the new C++ API to make the code work in a more C++ appropriate way. This leverages off of the prior experiments and hopefully brings a more readable and debuggable code implementation.
NOTE: THIS IS STILL A WORK IN PROGRESS