Looking at std::atomic
and it's default specializations I read:
These specializations have standard layout, trivial default constructors, and trivial destructors.
I also read for is_lock_free
:
All atomic types except for
std::atomic_flag
may be implemented using mutexes or other locking operations, rather than using the lock-free atomic CPU instructions. Atomic types are also allowed to be sometimes lock-free, e.g. if only aligned memory accesses are naturally atomic on a given architecture, misaligned objects of the same type have to use locks.
Now here's the catch that I don't get:
How can any atomic
type where the Standard prescribes trivial ctor/dtor ever be using any kind of mutex -- all mutexes I ever came across required non-trivial initialization.
This leads to the following questions:
- Do major platforms provide any locking operation (like a mutex) that is "initalization free" per object. (That would be the "other locking operations".)
- Is there any known implementation today for default
std::atomic
specializations that isn't lock free (and still fulfills the trivial ctor/dtor requirement)? - Am I simply confusing something here? :-)
It seems to me that even the simplest spin lock (see atomic_flag
) needs non-trivial initialization, so I fail to see how this could be implemented.
Disclaimer: Purely out of academic interest, as this kinda jumped out on me while reading these docs.
Here is a possible solution: if an atomic operation uses a lock but has a trivial constructor and destructor, the mutex may be a global mutex shared between many atomic values.
This, I believe, is the case that the standard authors were allowing. It is possible to use trivial constructors and destructors for mutexes with static duration on some common platforms (such as POSIX).
If the
std::atomic
default constructors were permitted to be non-trivial, then it would be difficult to use them during initialization.Because
my_flag
has a trivial constructor, it is static-initialized. Static initialization happens before dynamic initialization. So you can be sure that all the globalstd::atomic
variables are initialized before your constructors run.