@@ -35,7 +35,7 @@ fn spin_until(loc: &AtomicUsize, val: usize) -> usize {
3535
3636/// Check that the function produces the intended set of outcomes.
3737#[ track_caller]
38- fn check_all_outcomes < T : Eq + std:: hash:: Hash + std:: fmt:: Display > (
38+ fn check_all_outcomes < T : Eq + std:: hash:: Hash + std:: fmt:: Debug > (
3939 expected : impl IntoIterator < Item = T > ,
4040 generate : impl Fn ( ) -> T ,
4141) {
@@ -47,7 +47,7 @@ fn check_all_outcomes<T: Eq + std::hash::Hash + std::fmt::Display>(
4747 let tries = expected. len ( ) * 12 ;
4848 for i in 0 ..tries {
4949 let val = generate ( ) ;
50- assert ! ( expected. contains( & val) , "got an unexpected value: {val}" ) ;
50+ assert ! ( expected. contains( & val) , "got an unexpected value: {val:? }" ) ;
5151 seen. insert ( val) ;
5252 if i > tries / 2 && expected. len ( ) == seen. len ( ) {
5353 // We saw everything and we did quite a few tries, let's avoid wasting time.
@@ -57,7 +57,7 @@ fn check_all_outcomes<T: Eq + std::hash::Hash + std::fmt::Display>(
5757 // Let's see if we saw them all.
5858 for val in expected {
5959 if !seen. contains ( & val) {
60- panic ! ( "did not get value that should be possible: {val}" ) ;
60+ panic ! ( "did not get value that should be possible: {val:? }" ) ;
6161 }
6262 }
6363}
@@ -163,10 +163,46 @@ fn faa_replaced_by_load() {
163163 } ) ;
164164}
165165
166+ /// Checking that the weaker release sequence example from
167+ /// <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0982r0.html> can actually produce the
168+ /// new behavior (`Some(0)` in our version).
169+ fn weaker_release_sequences ( ) {
170+ check_all_outcomes ( [ None , Some ( 0 ) , Some ( 1 ) ] , || {
171+ let x = static_atomic ( 0 ) ;
172+ let y = static_atomic ( 0 ) ;
173+
174+ let t1 = spawn ( move || {
175+ x. store ( 2 , Relaxed ) ;
176+ } ) ;
177+ let t2 = spawn ( move || {
178+ y. store ( 1 , Relaxed ) ;
179+ x. store ( 1 , Release ) ;
180+ x. store ( 3 , Relaxed ) ;
181+ } ) ;
182+ let t3 = spawn ( move || {
183+ if x. load ( Acquire ) == 3 {
184+ // In C++11, if we read the 3 here, and if the store of 1 was just before the store
185+ // of 3 in mo order (which it is because we fix the schedule), this forms a release
186+ // sequence, meaning we acquire the release store of 1, and we can thus never see
187+ // the value 0.
188+ // In C++20, this is no longer a release sequence, so 0 can now be observed.
189+ Some ( y. load ( Relaxed ) )
190+ } else {
191+ None
192+ }
193+ } ) ;
194+
195+ t1. join ( ) . unwrap ( ) ;
196+ t2. join ( ) . unwrap ( ) ;
197+ t3. join ( ) . unwrap ( )
198+ } ) ;
199+ }
200+
166201pub fn main ( ) {
167202 relaxed ( ) ;
168203 seq_cst ( ) ;
169204 initialization_write ( false ) ;
170205 initialization_write ( true ) ;
171206 faa_replaced_by_load ( ) ;
207+ weaker_release_sequences ( ) ;
172208}
0 commit comments