feat!: C++ callback wrapper + v8.0.30 release (closes #482)#494
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR completes the C++ binding migration for FPSS streaming onto the callback-based C ABI and cuts the v8.0.30 release by updating versions, changelogs, and the restored C++ fpss_smoke example.
Changes:
- Adds C++
tdx::FpssClientcallback registration (set_callback,set_inline_callback) and restoressdks/cpp/examples/fpss_smoke.cppon the callback path. - Promotes
[Unreleased]to the8.0.30release entry in both changelogs and updates C++ SDK docs accordingly. - Bumps versions to
8.0.30across Rust crates/tools and Node packages (plus lockfiles) to keep the repo version-synchronized.
Reviewed changes
Copilot reviewed 16 out of 21 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/server/Cargo.toml | Bump tool version to 8.0.30. |
| tools/server/Cargo.lock | Lockfile updates reflecting 8.0.30 dependencies. |
| tools/mcp/Cargo.toml | Bump tool version to 8.0.30. |
| tools/mcp/Cargo.lock | Lockfile updates reflecting 8.0.30 dependencies. |
| tools/cli/Cargo.toml | Bump CLI version to 8.0.30. |
| sdks/typescript/package.json | Bump npm package + optionalDependencies versions to 8.0.30. |
| sdks/typescript/npm/win32-x64-msvc/package.json | Bump platform package version to 8.0.30. |
| sdks/typescript/npm/linux-x64-gnu/package.json | Bump platform package version to 8.0.30. |
| sdks/typescript/npm/darwin-arm64/package.json | Bump platform package version to 8.0.30. |
| sdks/typescript/Cargo.toml | Bump napi crate version to 8.0.30. |
| sdks/typescript/Cargo.lock | Lockfile updates reflecting 8.0.30 dependencies. |
| sdks/python/Cargo.toml | Bump PyO3 crate version to 8.0.30. |
| sdks/python/Cargo.lock | Lockfile updates reflecting 8.0.30 dependencies. |
| sdks/cpp/README.md | Update C++ streaming docs to callback-driven API + inline callback notes. |
| sdks/cpp/include/thetadx.hpp | Implement callback registration wrappers and stable callback storage for C++ FPSS client. |
| sdks/cpp/examples/fpss_smoke.cpp | Restore FPSS smoke example using queued callback API. |
| ffi/Cargo.toml | Bump FFI crate version to 8.0.30. |
| docs-site/docs/changelog.md | Promote Unreleased to 8.0.30 release entry on docs site. |
| crates/thetadatadx/Cargo.toml | Bump core Rust crate version to 8.0.30. |
| CHANGELOG.md | Promote Unreleased to 8.0.30 release entry in root changelog. |
| Cargo.lock | Workspace lockfile updates reflecting 8.0.30 versions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+368
to
+374
| void set_callback(std::function<void(const FpssEvent&)> fn) { | ||
| callback_ = std::make_unique<std::function<void(const FpssEvent&)>>(std::move(fn)); | ||
| int rc = tdx_fpss_set_callback(handle_.get(), &FpssClient::callback_shim, callback_.get()); | ||
| if (rc < 0) { | ||
| callback_.reset(); | ||
| throw std::runtime_error("thetadatadx: " + detail::last_ffi_error()); | ||
| } |
Comment on lines
+382
to
+388
| void set_inline_callback(std::function<void(const FpssEvent&)> fn) { | ||
| callback_ = std::make_unique<std::function<void(const FpssEvent&)>>(std::move(fn)); | ||
| int rc = tdx_fpss_set_inline_callback(handle_.get(), &FpssClient::callback_shim, callback_.get()); | ||
| if (rc < 0) { | ||
| callback_.reset(); | ||
| throw std::runtime_error("thetadatadx: " + detail::last_ffi_error()); | ||
| } |
Comment on lines
358
to
362
| handle_ = std::move(other.handle_); | ||
| callback_ = std::move(other.callback_); | ||
| return *this; | ||
| } | ||
|
|
Comment on lines
+10
to
+14
| This release closes #482: the entire FPSS streaming stack — Rust core, | ||
| C ABI, Python, TypeScript, and C++ — moves to a callback-driven | ||
| delivery model backed by a single `StreamingDispatcher` SSOT. Bundles | ||
| PR #489 (dispatcher core), #490 (C ABI), #492 (Python), #493 | ||
| (TypeScript), and #494 (C++ wrapper). |
Comment on lines
+10
to
+14
| This release closes #482: the entire FPSS streaming stack — Rust core, | ||
| C ABI, Python, TypeScript, and C++ — moves to a callback-driven | ||
| delivery model backed by a single `StreamingDispatcher` SSOT. Bundles | ||
| PR #489 (dispatcher core), #490 (C ABI), #492 (Python), #493 | ||
| (TypeScript), and #494 (C++ wrapper). |
userFRM
added a commit
that referenced
this pull request
May 6, 2026
…/ move-assign set_callback / set_inline_callback now stage the new std::function into a local unique_ptr and only adopt it into callback_ after tdx_fpss_set_callback returns 0. The C ABI rejects subsequent registrations with -1 while keeping the previously installed (callback, ctx) live, so overwriting callback_ before checking the return code dangled the Rust-side ctx into freed storage. operator=(FpssClient&&) now drains the existing handle via tdx_fpss_shutdown before dropping the old callback_. tdx_fpss_shutdown stops the FPSS reader and joins the dispatcher drain thread before returning, so once it completes no thread can still observe the old ctx pointer.
Migrate the C++ wrapper to the callback C ABI shipped in PR #490. `tdx::FpssClient` gains two header-only methods that wrap `tdx_fpss_set_callback` / `tdx_fpss_set_inline_callback`: void set_callback(std::function<void(const FpssEvent&)> fn); void set_inline_callback(std::function<void(const FpssEvent&)> fn); The Client owns a `unique_ptr<std::function<...>>` -- a stable address survives moves of the owning client and is handed to the C ABI as the `void* ctx`. A free `extern "C"` shim recovers the function from `ctx` and invokes it with `const FpssEvent&`, swallowing any propagating exception so unwinding cannot cross the Rust/C boundary. The destructor's call to `tdx_fpss_shutdown` runs before the function storage is freed, so the dispatcher / reader threads cannot dereference stale state. `fpss_smoke.cpp` is restored on the callback path -- `#error` directive deleted, example rewritten to subscribe, register a queued callback, print events for five seconds, and exit cleanly. The CMake target builds clean. `sdks/cpp/README.md` streaming section now documents callback registration as the only entry point with a dedicated note on the inline opt-in's microsecond-budget contract. Version bump 8.0.29 -> 8.0.30 via `scripts/bump_version.py`. The [Unreleased] CHANGELOG block becomes `## [8.0.30] - 2026-05-06` -- the single coherent #482 release that bundles the dispatcher core (#489), C ABI callback (#490), and C++ wrapper migration. Python (#492) and TypeScript (#493) entries land when those PRs merge. Closes #482.
…/ move-assign set_callback / set_inline_callback now stage the new std::function into a local unique_ptr and only adopt it into callback_ after tdx_fpss_set_callback returns 0. The C ABI rejects subsequent registrations with -1 while keeping the previously installed (callback, ctx) live, so overwriting callback_ before checking the return code dangled the Rust-side ctx into freed storage. operator=(FpssClient&&) now drains the existing handle via tdx_fpss_shutdown before dropping the old callback_. tdx_fpss_shutdown stops the FPSS reader and joins the dispatcher drain thread before returning, so once it completes no thread can still observe the old ctx pointer.
a886f3a to
74706c4
Compare
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.
Summary
Final binding migration for #482. The C++ wrapper moves to the callback C ABI shipped in #490, the
fpss_smokeexample is restored on the callback path, and the[Unreleased]CHANGELOG block becomes the v8.0.30 release that bundles the entire #482 stack.New C++ surface
sdks/cpp/include/thetadx.hpp, header-only ontdx::FpssClient:set_callbackwirestdx_fpss_set_callback(queued: dispatcher drain thread invokesfn, reader never blocks).set_inline_callbackwirestdx_fpss_set_inline_callback(inline:fnfires on the FPSS reader thread, microsecond-budget contract). The client owns aunique_ptr<std::function<...>>so the address handed to the C ABI asctxis stable across moves; a freeextern "C"shim recovers the function fromctxand swallows any propagating exception so unwinding cannot cross the Rust/C boundary.Release-note table — what v8.0.30 bundles
StreamingDispatcher+ bounded crossbeam queue +start_streaming_inlinetdx_*_set_callback/tdx_*_set_inline_callback;next_event/start_streamingremovednext_event/next_event_typedremovednextEventremovedtdx::FpssClient::set_callback/set_inline_callback;fpss_smokeexample restoredVersion bump
scripts/bump_version.py 8.0.30updated every Cargo.toml, everypackage.json, everyoptionalDependenciesentry, and everyCargo.lockin lockstep.Heads-up
[Unreleased]was promoted to## [8.0.30] - 2026-05-06on a state that includes only PR #489 + #490 in-tree. PR #492 (Python) and PR #493 (TypeScript) currently target the same[Unreleased]block; once they merge they will conflict on this CHANGELOG section. Per the staged plan they fold into the same v8.0.30 release notes — the merge order needs to be resolved by the maintainer.Test plan
cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspacecargo deny checkcargo run -p thetadatadx --bin generate_sdk_surfaces --features config-file -- --checkcargo check / clippy / test --no-runontools/mcpcargo check --lockedontools/server,sdks/python,sdks/typescriptpython3 scripts/check_version_sync.py→version sync: okcmake -S sdks/cpp -B build/cpp && cmake --build build/cpp— every target (thetadatadx_cpp,thetadatadx_example,thetadatadx_validate,thetadatadx_fpss_smoke) builds clean./build/cpp/thetadatadx_fpss_smoke creds.txt)Closes #482.