blob: addf6408c006f4b13425721121200aeb98e61c97 [file] [log] [blame]
//@compile-flags: -Zmiri-genmc -Zmiri-disable-stacked-borrows
//@revisions: check_count try_upgrade
// Check that various operations on `std::sync::Arc` are handled properly in GenMC mode.
//
// The number of explored executions in the expected output of this test may change if
// the implementation of `Arc` is ever changed, or additional optimizations are added to GenMC mode.
//
// The revision that tries to upgrade the `Weak` should never explore fewer executions compared to the revision that just accesses the `strong_count`,
// since `upgrade` needs to access the `strong_count` internally.
// There should always be more than 1 execution for both, since there is always the possibilility that the `Arc` has already been dropped, or it hasn't.
use std::sync::Arc;
fn main() {
let data = Arc::new(42);
// Clone the Arc, drop the original, check that memory still valid.
let data_clone = Arc::clone(&data);
drop(data);
assert!(*data_clone == 42);
// Create a Weak reference.
let weak = Arc::downgrade(&data_clone);
// Spawn a thread that uses the Arc.
let weak_ = weak.clone();
let handle = std::thread::spawn(move || {
// Try to upgrade weak reference.
// Depending on execution schedule, this may fail or succeed depending on whether this runs before or after the `drop` in the main thread.
#[cfg(check_count)]
let _strong_count = weak_.strong_count();
#[cfg(try_upgrade)]
if let Some(strong) = weak_.upgrade() {
assert_eq!(*strong, 42);
}
});
// Drop the last strong reference to the data.
drop(data_clone);
// Wait for the thread to finish.
handle.join().unwrap();
// The upgrade should fail now (all Arcs dropped).
assert!(weak.upgrade().is_none());
}