Skip to content

Commit e7c99a7

Browse files
committed
allow mixed-size atomic reads
1 parent addd05e commit e7c99a7

File tree

1 file changed

+16
-10
lines changed

1 file changed

+16
-10
lines changed

core/src/sync/atomic.rs

+16-10
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@
3333
//! atomic load (via the operations provided in this module). A "modification of an atomic object"
3434
//! refers to an atomic store.
3535
//!
36+
//! The most important aspect of this model is that conflicting non-synchronized accesses are
37+
//! Undefined Behavior unless both accesses are atomic. Here, accesses are *conflicting* if they
38+
//! affect overlapping regions of memory and at least one of them is a write. They are
39+
//! *non-synchronized* if neither of them *happens-before* the other, according to the
40+
//! happens-before order of the memory model.
41+
//!
3642
//! The end result is *almost* equivalent to saying that creating a *shared reference* to one of the
3743
//! Rust atomic types corresponds to creating an `atomic_ref` in C++, with the `atomic_ref` being
3844
//! destroyed when the lifetime of the shared reference ends. The main difference is that Rust
@@ -41,9 +47,10 @@
4147
//! objects" and "non-atomic objects" (with `atomic_ref` temporarily converting a non-atomic object
4248
//! into an atomic object).
4349
//!
44-
//! That said, Rust *does* inherit the C++ limitation that non-synchronized atomic accesses may not
45-
//! partially overlap: they must be either disjoint or access the exact same memory. This in
46-
//! particular rules out non-synchronized differently-sized accesses to the same data.
50+
//! That said, Rust *does* inherit the C++ limitation that non-synchronized conflicting atomic
51+
//! accesses may not partially overlap: they must be either disjoint or access the exact same
52+
//! memory. This in particular rules out non-synchronized differently-sized atomic accesses to the
53+
//! same data unless all accesses are reads.
4754
//!
4855
//! [cpp]: https://en.cppreference.com/w/cpp/atomic
4956
//! [cpp-intro.races]: https://timsong-cpp.github.io/cppwp/n4868/intro.multithread#intro.races
@@ -63,7 +70,7 @@
6370
//! let atomic = AtomicU16::new(0);
6471
//!
6572
//! thread::scope(|s| {
66-
//! // This is UB: conflicting concurrent accesses.
73+
//! // This is UB: conflicting non-synchronized accesses, at least one of which is non-atomic.
6774
//! s.spawn(|| atomic.store(1, Ordering::Relaxed)); // atomic store
6875
//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); // non-atomic write
6976
//! });
@@ -77,16 +84,15 @@
7784
//! });
7885
//!
7986
//! thread::scope(|s| {
80-
//! // This is fine, `join` synchronizes the code in a way such that atomic
81-
//! // and non-atomic accesses can't happen "at the same time".
87+
//! // This is fine: `join` synchronizes the code in a way such that the atomic
88+
//! // store happens-before the non-atomic write.
8289
//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed)); // atomic store
8390
//! handle.join().unwrap(); // synchronize
8491
//! s.spawn(|| unsafe { atomic.as_ptr().write(2) }); // non-atomic write
8592
//! });
8693
//!
8794
//! thread::scope(|s| {
88-
//! // This is UB: using differently-sized atomic accesses to the same data.
89-
//! // (It would be UB even if these are both loads.)
95+
//! // This is UB: non-synchronized conflicting differently-sized atomic accesses.
9096
//! s.spawn(|| atomic.store(1, Ordering::Relaxed));
9197
//! s.spawn(|| unsafe {
9298
//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic);
@@ -95,8 +101,8 @@
95101
//! });
96102
//!
97103
//! thread::scope(|s| {
98-
//! // This is fine, `join` synchronizes the code in a way such that
99-
//! // differently-sized accesses can't happen "at the same time".
104+
//! // This is fine: `join` synchronizes the code in a way such that
105+
//! // the 1-byte store happens-before the 2-byte store.
100106
//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed));
101107
//! handle.join().unwrap();
102108
//! s.spawn(|| unsafe {

0 commit comments

Comments
 (0)