| 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).addr(), 1); | |
| assert_eq!(get(k2).addr(), 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" | |
| ); | |
| } |