What does the carries_dependency attribute mean?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
[[carries_dependency]] is a C++ attribute intended for highly specialized lock-free code that relies on dependency ordering. It tells the compiler that a dependency chain should be preserved across a function boundary for memory-order reasoning. Most modern C++ code never needs it, and many projects should avoid it for clarity.
Background: Dependency Ordering
In atomic programming, one thread may publish data and another thread may consume a pointer or index to that data. Some architectures preserve certain data-dependent ordering without a full acquire barrier. Historically, memory_order_consume attempted to model this, but practical compiler support has been weak and complicated.
[[carries_dependency]] was introduced to help propagate dependency information through function calls.
Where the Attribute Can Appear
You may apply it to function parameters or return values in declarations to indicate dependency transfer intent.
In theory, this signals that dependency from read_head result is carried into read_value argument usage.
Why It Is Rare in Production Code
In practice, many compilers map memory_order_consume to memory_order_acquire or otherwise do not provide robust dependency-based optimization. As a result, codebases often prefer explicit acquire semantics and avoid fragile dependency assumptions.
Safer mainstream approach:
This is clearer to reviewers and tools, and behavior is more portable.
Relationship to std::kill_dependency
C++ also provides std::kill_dependency, used to intentionally break dependency chains when needed for optimization. Both features target advanced use cases and are uncommon in everyday application code.
Most teams should treat this as expert-level tuning territory.
Guidance for Real Projects
Use [[carries_dependency]] only when all conditions are true.
- You are writing lock-free low-level components.
- You have measured architecture-specific performance impact.
- Toolchain behavior is validated on your supported compilers.
- Team reviewers are comfortable maintaining this memory-model complexity.
If any condition is missing, use acquire-release semantics for maintainability.
Testing and Verification Strategy
For low-level concurrency code, combine correctness and performance validation.
- Stress tests with high thread counts and randomized schedules.
- Sanitizers such as ThreadSanitizer for race detection.
- Cross-compiler CI to detect divergent behavior.
- Microbenchmarks tied to target architecture.
Without this discipline, dependency-order tricks are more risk than value.
Function Boundary Example and Intent
The attribute primarily exists for cases where dependency should survive helper function layers. Without annotation, compiler reasoning may drop that dependency information.
Even with this form, many teams still choose memory_order_acquire because intent is clearer and tooling support is stronger. Treat dependency attributes as low-level optimization hints, not correctness foundations.
Portability and Maintenance Tradeoff
Concurrency bugs are expensive to diagnose, so readability often beats theoretical micro-optimizations. If you adopt dependency-oriented code, document assumptions in comments and architecture notes, and keep focused regression tests for each supported compiler toolchain.
Common Pitfalls
- Assuming
[[carries_dependency]]provides universal speedups. - Using it in business-logic code where readability is more important.
- Relying on
memory_order_consumebehavior without compiler-specific validation. - Mixing dependency-based and acquire-release models inconsistently.
- Introducing subtle ordering bugs that only appear on specific CPU architectures.
Summary
[[carries_dependency]]is a specialized hint for dependency-chain propagation.- It is related to lock-free optimization and
memory_order_consumesemantics. - Real-world compiler support and portability concerns limit practical use.
- Most projects should prefer explicit acquire-release ordering.
- Use dependency attributes only in carefully measured, low-level concurrency code.

