C++ SDK: Thread-Safety Contract
C++ SDK: Thread-Safety Contract
Section titled “C++ SDK: Thread-Safety Contract”If you embed the SDK in a GUI or otherwise multi-threaded application, follow this contract so you call it without data races. It states which calls are safe to make concurrently and which are not.
Single-owner-at-a-time for mutating calls
Section titled “Single-owner-at-a-time for mutating calls”A single aureva::Api instance is safe to use from one thread at a time.
Do not call the mutating methods init(), license(), or check() concurrently on the same instance. These calls advance the instance’s state machine; issuing them at the same time from different threads is unsupported.
Typical pattern: run init() and license() on a worker (off your UI / render thread, since they block on the network), and schedule check() from a single timer or loop — never overlapping with another mutating call on the same instance.
Cross-thread reads are safe
Section titled “Cross-thread reads are safe”Reading the published snapshots — app.response and app.user_data — from a thread other than the one making the most recent mutating call is safe and non-blocking.
The SDK publishes those snapshots under its own internal synchronization, so a reader on a separate thread (for example a render thread polling the current authorization status to draw UI) always observes an internally consistent value and never a torn or partial one. The reader never blocks on the network-holding work that license() / check() perform.
// Worker thread:app.license(key); // mutating call — single owner
// Render thread (concurrently): safe, non-blocking snapshot readsif (app.response.success) { drawStatus(app.user_data.tier, app.user_data.expiry);}While the background session is alive, the SDK runs an internal heartbeat thread. The SDK synchronizes its internal shared state — the authorization verdict, the session state, the subscription / entitlement cache, and the lockout state — so the heartbeat thread and the reads performed by check() and user_data do not data-race.
Concurrent mutation is undefined and unsupported
Section titled “Concurrent mutation is undefined and unsupported”If you violate the contract — for example by issuing concurrent mutating calls on a single instance — the resulting behavior is undefined and unsupported, not guaranteed. The SDK is not required to defend against this misuse beyond the guarantees stated here.
Multiple keys or applications — use a separate instance
Section titled “Multiple keys or applications — use a separate instance”If you need concurrent authentication for multiple keys or applications, use a separate aureva::Api instance per logical session.
Distinct instances do not share mutable SDK state in a way that would cause cross-instance races. The one process- and machine-global facility is the HWID store on disk; the SDK serializes access to it with a process-wide named lock, so concurrent instances on the same machine coordinate and never corrupt the persisted identifier.
Summary
Section titled “Summary”| Operation | Rule |
|---|---|
init() / license() / check() on one instance | One thread at a time — never concurrently |
Reading response / user_data | Safe and non-blocking from any thread |
| Concurrent mutating calls on one instance | Undefined / unsupported |
| Multiple keys or applications | One aureva::Api instance per logical session |
| HWID store | Shared but synchronized by the SDK across instances |
Next steps
Section titled “Next steps”- Getting Started — download, build, and call the SDK
- Auth Flow & Error Surfaces — the heavy flow and the error surfaces