Built-in concurrency policies:
policy::concurrency::nonepolicy::concurrency::fencedpolicy::concurrency::fenced_relaxedpolicy::concurrency::fenced_acq_relpolicy::concurrency::fenced_seq_cst
General guidance:
- Use
nonefor single-threaded paths. - Use
fencedorfenced_seq_cstfirst for simple correctness. - Use relaxed/acq_rel variants only when you have clear memory-order requirements.
using shared_t = mcpplibs::primitives::primitive<
int,
mcpplibs::primitives::policy::value::checked,
mcpplibs::primitives::policy::concurrency::fenced,
mcpplibs::primitives::policy::error::expected>;
shared_t counter{0};Use:
counter.load()counter.store(v)counter.compare_exchange(expected, desired)
auto expected = counter.load();
while (!counter.compare_exchange(expected, expected + 1)) {
}This is the typical lock-free increment style used in multi-threaded updates.
For practical concurrent workloads, combine:
- writer threads updating operands through
store - reader threads calling
operations::add/operations::sub - optional sink updates via
storeand checkpointcompare_exchange
See examples/ex05_concurrency_policy.cpp for a representative end-to-end workload.
Fenced access handlers require underlying representations to satisfy atomic-ref constraints (trivially copyable and alignment-compatible).
Operation dispatch consistency and concurrency fences are policy-driven. Do not assume synchronization semantics unless explicitly configured.
Operation results are std::expected<...>. Always handle has_value().
- Extension guide: ./extension.md
- API concurrency details: ../../api/en/README.md