pw_alignment#
Natural object alignment, guaranteed
Stable C++17
Transparent: Enforce natural alignment without any changes to how your objects are used.
Efficient: Prevent your compiler from emitting libcalls to builtin atomic functions and ensure it uses native atomic instructions instead.
#include "pw_alignment/alignment.h"
// Passing a `std::optional<bool>` to `__atomic_exchange` might not replace
// the call with native instructions if the compiler cannot determine all
// instances of this object will happen to be aligned.
std::atomic<std::optional<bool>> maybe_nat_aligned_obj;
// `pw::NaturallyAligned<...>` forces the object to be aligned to its size,
// so passing it to `__atomic_exchange` will result in a replacement with
// native instructions.
std::atomic<pw::NaturallyAligned<std::optional<bool>>> nat_aligned_obj;
// Shorter spelling for the same as above.
pw::AlignedAtomic<std::optional<bool>> also_nat_aligned_obj;
pw_alignment
portably ensures that your compiler uses native atomic
instructions rather than libcalls to builtin atomic functions. Take for example
std::atomic<std::optional<bool>>
. Accessing the underlying object normally
involves a call to a builtin __atomic_*
function. The problem is that the
compiler sometimes can’t determine that the size of the object is the same
as the size of its alignment. pw_alignment
ensures that an object aligns to
its size so that compilers can always make this optimization.
Warning
Using std::optional<bool>
is only a workaround that may not work with all
compilers. This specifically does not work when targetting ARM cortex M0.
Additionally, std::optional<bool>
is not the recommended way to represent
a ternary variable.
Get started#
Add @pigweed//pw_alignment
to the deps
list in your Bazel target:
cc_library("...") {
# ...
deps = [
# ...
"@pigweed//pw_alignment",
# ...
]
}
This assumes that your Bazel WORKSPACE
has a repository named @pigweed
that points to the upstream Pigweed repository.
Add $dir_pw_alignment
to the deps
list in your pw_executable()
build target:
pw_executable("...") {
# ...
deps = [
# ...
"$dir_pw_alignment",
# ...
]
}
Add pw_alignment
to your pw_add_library
or similar CMake target:
pw_add_library(my_library STATIC
HEADERS
...
PRIVATE_DEPS
# ...
pw_alignment
# ...
)
API reference#
- group pw_alignment
Typedefs
-
template<typename T>
using AlignedAtomic = std::atomic<NaturallyAligned<T>># Ensures the object held by
std::atomic
is naturally aligned. This enables the compiler to replace libcalls to atomic functions with native instructions when appropriate.AlignedAtomic
is a convenience wrapper.Example:
#include "pw_alignment/alignment.h" pw::AlignedAtomic<std::optional<bool>> mute_enable{};
std::optional<bool>
has a size of 2 but alignment of 1, which would normally lower to an__atomic_*
libcall, butpw::NaturallyAligned
instd::atomic
tells the compiler to align the object to 2 bytes, which satisfies the requirements for replacing__atomic_*
with native instructions.
-
template<typename T>
struct NaturallyAligned : public T# Ensures the object is naturally aligned to a power of 2 bytes greater than or equal to its size.
NaturallyAligned
is a wrapper class.Example:
#include "pw_alignment/alignment.h" std::atomic<pw::NaturallyAligned<std::optional<bool>>> nat_aligned_obj;
-
template<typename T>