Consider a library that uses stdatomic.h header. This one will not compile in C++ project, especially if it is required to use structure with atomic components.
How to properly implement library with atomic components, to build with C or C++ compiler? Small demo that builds well - but it seems very shady and holds potential undefined behavior.
lib.h header file
#ifndef LIB_HDR_H
#define LIB_HDR_H
#include <stdint.h>
#include <stddef.h>
#if defined(__cplusplus)
/* C++ atomic header */
#include <atomic>
#define lib_size_t std::atomic<size_t>
#else
/* STDATOMIC C header */
#include <stdatomic.h>
typedef atomic_size_t lib_size_t;
#endif
#if defined(__cplusplus)
extern "C" {
#endif /* defined(__cplusplus) */
/* Tricky part here... */
typedef struct {
lib_size_t a;
lib_size_t b;
} lib_t;
void lib_init(lib_t *l);
#if defined(__cplusplus)
}
#endif /* defined(__cplusplus) */
#endif /* LIB_HDR_H */
lib.c implementation file
#include "lib.h"
/* Not much to do here right now... */
void lib_init(lib_t* l) {
/* These operations shall be atomic */
l->a = 5;
l->b = 10;
}
C++ application file that uses the library
#include <iostream>
#include "lib.h"
lib_t my_lib;
int main() {
lib_init(&my_lib);
}
In C++
std::atomic_size_tis an alias forstd::atomic<size_t>and in Catomic_size_tis an alias for_Atomic size_t.With a
using std::atomic_size_tin the C++ side of the#if, you can simply usetypedef atomic_size_t lib_size_t;for both languages and starting with C++23 you can include<stdatomic.h>and usetypedef atomic_size_t lib_size_t;directly in both C and C++.The two types are not the same in the same way that
size_tis supposed to be the same type in both C and C++, because C++ doesn't have any equivalent to the_Atomicmodifier. So it is not obvious that the ABI handles the two types in the same way and that what you are doing is allowed. (In practice, most real implementations did handle them the same way.)However, the C++23 standard draft contains an implementation recommendation that same representation and compatibility of memory ordering mechanism between
_Atmomic Tandstd::atomic<T>should be assured. Of course this can only be a recommendation and the details will be on the particular implementation to decide.So, assuming your compiler supports both C atomics and C++ atomics, it should make an effort to support the approach you are using here, although that is not a requirement for conformance. However, it doesn't seem to be a given. See the proposal introducing the implementation recommendation P0943 for some details. For example it mentions that GCC had an alignment difference between 64-bit atomic C vs. C++ types on 32-bit targets like ARMv7 and x86.
This was probably a GCC bug, like x86 GCC bug 65146 resulting in lack of atomicity for
_Atomic long longinside structs in some C programs, which was fixed in GCC11. It went unfixed for a long time partly because GCC already chose to align 8-byte objects by 8 when they were outside structs so it was allowed to. (g++ originally had an equivalent bug, but it was fixed withalignas()in thestd::atomic<>class definition in library headers, vs._Atomicrequiring the compiler internals to do that.) We don't know for sure what ARMv7 detail they were talking about, but it's likely similar and probably only affects 64-bit types.So you probably need to verify that this is properly supported for your specific compiler/architecture.