| use super::StaticKey; |
| use crate::ptr; |
| |
| #[test] |
| fn smoke() { |
| static K1: StaticKey = StaticKey::new(None); |
| static K2: StaticKey = StaticKey::new(None); |
| |
| unsafe { |
| assert!(K1.get().is_null()); |
| assert!(K2.get().is_null()); |
| K1.set(ptr::invalid_mut(1)); |
| K2.set(ptr::invalid_mut(2)); |
| assert_eq!(K1.get() as usize, 1); |
| assert_eq!(K2.get() as usize, 2); |
| } |
| } |
| |
| #[test] |
| fn destructors() { |
| use crate::mem::ManuallyDrop; |
| use crate::sync::Arc; |
| use crate::thread; |
| |
| unsafe extern "C" fn destruct(ptr: *mut u8) { |
| drop(Arc::from_raw(ptr as *const ())); |
| } |
| |
| static KEY: StaticKey = StaticKey::new(Some(destruct)); |
| |
| let shared1 = Arc::new(()); |
| let shared2 = Arc::clone(&shared1); |
| |
| unsafe { |
| assert!(KEY.get().is_null()); |
| KEY.set(Arc::into_raw(shared1) as *mut u8); |
| } |
| |
| thread::spawn(move || unsafe { |
| assert!(KEY.get().is_null()); |
| KEY.set(Arc::into_raw(shared2) as *mut u8); |
| }) |
| .join() |
| .unwrap(); |
| |
| // Leak the Arc, let the TLS destructor clean it up. |
| let shared1 = unsafe { ManuallyDrop::new(Arc::from_raw(KEY.get() as *const ())) }; |
| assert_eq!( |
| Arc::strong_count(&shared1), |
| 1, |
| "destructor should have dropped the other reference on thread exit" |
| ); |
| } |