| //@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()); | |
| } |