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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#![unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")]

// 共有三种线程本地实现: "static"、"fast"、"OS"。
// "OS" 线程本地密钥类型通过特定于平台的 API 调用访问并且速度很慢,而 "fast" 密钥类型通过 LLVM 生成的代码访问,其中 TLS 密钥由链接器设置。
//
// "static" 是一个单一静态线程就足够的平台。

cfg_if::cfg_if! {
    if #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] {
        #[doc(hidden)]
        mod static_local;
        #[doc(hidden)]
        pub use static_local::{Key, thread_local_inner};
    } else if #[cfg(target_thread_local)] {
        #[doc(hidden)]
        mod fast_local;
        #[doc(hidden)]
        pub use fast_local::{Key, thread_local_inner};
    } else {
        #[doc(hidden)]
        mod os_local;
        #[doc(hidden)]
        pub use os_local::{Key, thread_local_inner};
    }
}

mod lazy {
    use crate::cell::UnsafeCell;
    use crate::hint;
    use crate::mem;

    pub struct LazyKeyInner<T> {
        inner: UnsafeCell<Option<T>>,
    }

    impl<T> LazyKeyInner<T> {
        pub const fn new() -> LazyKeyInner<T> {
            LazyKeyInner { inner: UnsafeCell::new(None) }
        }

        pub unsafe fn get(&self) -> Option<&'static T> {
            // SAFETY: 调用者必须确保绝不向内部 cell 传递任何引用,也不要向所述 cell 内部的 Option<T> 进行可变引用。
            // 尽管'static 的生命周期本身是不安全的,这使 get 方法变得不安全,但这使引用变得安全。
            //
            //
            unsafe { (*self.inner.get()).as_ref() }
        }

        /// 调用者必须确保没有激活引用:此方法需要唯一的访问权限。
        ///
        pub unsafe fn initialize<F: FnOnce() -> T>(&self, init: F) -> &'static T {
            // 预先执行初始化,然后将其移动到我们的插槽中,以防万一初始化失败。
            //
            let value = init();
            let ptr = self.inner.get();

            // SAFETY:
            //
            // 请注意,从理论上讲,它只能是 `*ptr = Some(value)`,但是由于编译器当前将使用类似以下内容的代码生成该模式:
            //
            //      ptr::drop_in_place(ptr)
            //      ptr::write(ptr, Some(value))
            //
            // 由于这种模式,`ptr` 中的值的析构函数有可能重新访问 TLS (例如,如果正在递归初始化),在这种情况下,将有一个指向相同值的 `&` 和 `&mut` 指针 (违反别名)。
            // 为了避免设置 "我正在运行析构函数" 标志,我们只使用 `mem::replace`,它应该以稍微不同的方式对操作进行排序,并确保调用安全。
            //
            // 前提条件还确保了我们是目前唯一访问 `self` 的计算机,因此可以很好地进行替换。
            //
            //
            //
            //
            //
            //
            unsafe {
                let _ = mem::replace(&mut *ptr, Some(value));
            }

            // SAFETY: 通过调用 `mem::replace`,可以确保 `ptr` 后面有一个 `Some`,而不是 `None`,因此将永远无法到达 `unreachable_unchecked`。
            //
            //
            unsafe {
                // 存储 `Some` 之后,我们想对刚刚存储的内容进行引用。
                // 尽管我们可以在这里使用 `unwrap`,并且它应该始终有效,但是根据经验,似乎并没有总是对其进行优化,这意味着使用 `try_with` 之类的东西可能会引入 panic 代码并导致大规模的膨胀。
                //
                //
                //
                match *ptr {
                    Some(ref x) => x,
                    None => hint::unreachable_unchecked(),
                }
            }
        }

        /// 其他方法在取 &self 时分发引用。
        /// 因此,此方法的调用者必须确保没有 `&` 和 `&mut` 同时可用和使用。
        ///
        #[allow(unused)]
        pub unsafe fn take(&mut self) -> Option<T> {
            // SAFETY: 有关此方法,请参见文档注释。
            unsafe { (*self.inner.get()).take() }
        }
    }
}