summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys/windows/thread_local_key/tests.rs
blob: c95f383fb90e3cbc88a0567c779852c289c7a876 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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"
    );
}