| use super::{LazyKey, get, set}; |
| use crate::ptr; |
| |
| #[test] |
| fn smoke() { |
| static K1: LazyKey = LazyKey::new(None); |
| static K2: LazyKey = LazyKey::new(None); |
| |
| let k1 = K1.force(); |
| let k2 = K2.force(); |
| assert_ne!(k1, k2); |
| |
| assert_eq!(K1.force(), k1); |
| assert_eq!(K2.force(), k2); |
| |
| unsafe { |
| assert!(get(k1).is_null()); |
| assert!(get(k2).is_null()); |
| set(k1, ptr::without_provenance_mut(1)); |
| set(k2, ptr::without_provenance_mut(2)); |
| assert_eq!(get(k1) as usize, 1); |
| assert_eq!(get(k2) 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(unsafe { Arc::from_raw(ptr as *const ()) }); |
| } |
| |
| static KEY: LazyKey = LazyKey::new(Some(destruct)); |
| |
| let shared1 = Arc::new(()); |
| let shared2 = Arc::clone(&shared1); |
| |
| let key = KEY.force(); |
| unsafe { |
| assert!(get(key).is_null()); |
| set(key, Arc::into_raw(shared1) as *mut u8); |
| } |
| |
| thread::spawn(move || unsafe { |
| let key = KEY.force(); |
| assert!(get(key).is_null()); |
| set(key, 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(get(key) as *const ())) }; |
| assert_eq!( |
| Arc::strong_count(&shared1), |
| 1, |
| "destructor should have dropped the other reference on thread exit" |
| ); |
| } |