Ah, interesting. For the purposes of exclusivity, atomic accesses are distinct from either read or write accesses.
I believe the practical problem is with compiler optimizations (and instruction reordering). I found Hans Boehm's classic 2011 article a good read on this.
To be clear, this proposal does not expose any Swift-native atomic operations, so such things aren't really on the table yet. Later on, as we hopefully start formalizing Swift's concept of memory, I do think there will be plenty of opportunity to define things that C/C++ leaves undefined. But the need for continued interoperability between these languages means that we ought to be careful not to let them diverge too much. C++ is not standing still -- extensions such as tearing atomics are being discussed, and the memory model is being refined with every new version of the standard. I think it would be best if we kept things in sync as much as possible.
Which is not to say Swift cannot do things its own way or go a little bit ahead of where C++ is. The APIs provided in the initial version of this proposal (now in the supplementary package) already made some (inconsequential) departures from C++17: atomic operations are expected to have lock-free implementations, and CAS already supports all combinations of success/failure orderings. (Although internally it does currently "round them up" to the nearest C-supported combos, for obvious reasons.)
I expect we would eventually provide limited support for mixed atomic/nonatomic access, probably through something like explicit nonatomicLoad
operations. (I don't know if this would happen before or after C++ takes a similar step.) Allowing/encouraging regular everyday reads of "atomic" memory locations feels like it would be a mistake, though -- which is one reason why I am so hesitant about directly exposing pointer-based atomics.
Why exactly do you think mixed atomic-nonatomic access is worth bringing up at this point?