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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
use super::lazy::LazyKeyInner;
use crate::cell::Cell;
use crate::sys::thread_local_dtor::register_dtor;
use crate::{fmt, mem, panic};

#[doc(hidden)]
#[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)]
#[allow_internal_unsafe]
#[unstable(feature = "thread_local_internals", issue = "none")]
#[rustc_macro_transparency = "semitransparent"]
pub macro thread_local_inner {
    // 用于为常量初始化的线程局部变量生成 `LocalKey` 值
    (@key $t:ty, const $init:expr) => {{
        #[inline]
        #[deny(unsafe_op_in_unsafe_fn)]
        unsafe fn __getit(
            _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
        ) -> $crate::option::Option<&'static $t> {
            const INIT_EXPR: $t = $init;
            // 如果平台支持 `#[thread_local]`,请使用它。
            #[thread_local]
            static mut VAL: $t = INIT_EXPR;

            // 如果不需要 dtor,我们可以做一些 "非常原始" 的事情,然后开始。
            //
            if !$crate::mem::needs_drop::<$t>() {
                unsafe {
                    return $crate::option::Option::Some(&VAL)
                }
            }

            // 0 == dtor 未注册
            // 1 == dtor 已注册,dtor 未运行
            // 2 == dtor 已注册并正在运行或已运行
            #[thread_local]
            static mut STATE: $crate::primitive::u8 = 0;

            unsafe extern "C" fn destroy(ptr: *mut $crate::primitive::u8) {
                let ptr = ptr as *mut $t;

                unsafe {
                    $crate::debug_assert_eq!(STATE, 1);
                    STATE = 2;
                    $crate::ptr::drop_in_place(ptr);
                }
            }

            unsafe {
                match STATE {
                    // 0 == 我们还没有注册析构函数,所以现在注册。
                    //
                    0 => {
                        $crate::thread::local_impl::Key::<$t>::register_dtor(
                            $crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8,
                            destroy,
                        );
                        STATE = 1;
                        $crate::option::Option::Some(&VAL)
                    }
                    // 1 == 析构函数已注册且值有效,因此返回指针。
                    //
                    1 => $crate::option::Option::Some(&VAL),
                    // 否则析构函数已经运行,所以我们不能授予访问权限。
                    //
                    _ => $crate::option::Option::None,
                }
            }
        }

        unsafe {
            $crate::thread::LocalKey::new(__getit)
        }
    }},

    // 用于为 `thread_local!` 生成 `LocalKey` 值
    (@key $t:ty, $init:expr) => {
        {
            #[inline]
            fn __init() -> $t { $init }

            #[inline]
            unsafe fn __getit(
                init: $crate::option::Option<&mut $crate::option::Option<$t>>,
            ) -> $crate::option::Option<&'static $t> {
                #[thread_local]
                static __KEY: $crate::thread::local_impl::Key<$t> =
                    $crate::thread::local_impl::Key::<$t>::new();

                // FIXME: 当宏不再对丢失/额外不安全块发出警告时,请删除 #[allow(...)] 标记。
                // See https://github.com/rust-lang/rust/issues/74838.
                //
                #[allow(unused_unsafe)]
                unsafe {
                    __KEY.get(move || {
                        if let $crate::option::Option::Some(init) = init {
                            if let $crate::option::Option::Some(value) = init.take() {
                                return value;
                            } else if $crate::cfg!(debug_assertions) {
                                $crate::unreachable!("missing default value");
                            }
                        }
                        __init()
                    })
                }
            }

            unsafe {
                $crate::thread::LocalKey::new(__getit)
            }
        }
    },
    ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
        $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
            $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
    },
}

#[derive(Copy, Clone)]
enum DtorState {
    Unregistered,
    Registered,
    RunningOrHasRun,
}

// 此数据结构体经过精心构造,因此快速路径仅包含 x86 上的一个分支。
// 为了避免在 OSX 上重复查找 tls,必须进行优化。
//
// LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
//
pub struct Key<T> {
    // 如果 `LazyKeyInner::get` 返回 `None`,则表明:
    //   * 该值从未初始化
    //   * 该值正在递归初始化
    //   * 该值已被销毁或正在被销毁。要确定哪种 `None`,请检查 `dtor_state`。
    //
    //
    // 这对快速路径非常优化,它非常友好 - 已初始化但尚未丢弃。
    //
    inner: LazyKeyInner<T>,

    // 跟踪析构函数状态的元数据。
    // 请记住,此变量是线程局部的,而不是局部的。
    dtor_state: Cell<DtorState>,
}

impl<T> fmt::Debug for Key<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Key").finish_non_exhaustive()
    }
}

impl<T> Key<T> {
    pub const fn new() -> Key<T> {
        Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) }
    }

    // 请注意,这只是一个可公开调用的函数,仅适用于线程局部变量的 const 初始化形式,基本上是一种调用 std 中其他地方定义的免费 `register_dtor` 函数的方法。
    //
    //
    pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
        unsafe {
            register_dtor(a, dtor);
        }
    }

    pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
        // SAFETY: 有关详细信息,请参见 `LazyKeyInner::get` 和 `try_initialize` 的定义。
        //
        // 调用者必须确保在调用此内部 cell 或内部 T 时永远不会对它起作用。
        //
        // `try_initialize` 为此而依赖于传递的 `init` 函数。
        //
        //
        unsafe {
            match self.inner.get() {
                Some(val) => Some(val),
                None => self.try_initialize(init),
            }
        }
    }

    // 每个快速线程局部变量只调用一次 `try_initialize`,除非在 thread_local dtor 引用其他 thread_local 的极端情况下,或者它正在被递归初始化。
    //
    //
    // Macos: 内联这个函数会导致每个调用到 `Key::get` 时执行两次 `tlv_get_addr` 调用。
    // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
    //
    //
    #[inline(never)]
    unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
        // SAFETY: 请参见上面的注释 (此函数文档)。
        if !mem::needs_drop::<T>() || unsafe { self.try_register_dtor() } {
            // SAFETY: 请参见上面的注释 (此函数文档)。
            Some(unsafe { self.inner.initialize(init) })
        } else {
            None
        }
    }

    // 每个快速线程局部变量只调用一次 `try_register_dtor`,除非在 thread_local dtor 引用其他 thread_local 的极端情况下,或者它正在被递归初始化。
    //
    //
    unsafe fn try_register_dtor(&self) -> bool {
        match self.dtor_state.get() {
            DtorState::Unregistered => {
                // SAFETY: dtor 注册发生在初始化之前。
                // 使用 `destroy_value<T>` 时将 `self` 作为指针传递是安全的,因为函数将建立指向 Key<T> 的指针,Key<T> 是 self 的类型,因此可以找到正确的大小。
                //
                //
                //
                unsafe { register_dtor(self as *const _ as *mut u8, destroy_value::<T>) };
                self.dtor_state.set(DtorState::Registered);
                true
            }
            DtorState::Registered => {
                // 递归初始化
                true
            }
            DtorState::RunningOrHasRun => false,
        }
    }
}

unsafe extern "C" fn destroy_value<T>(ptr: *mut u8) {
    let ptr = ptr as *mut Key<T>;

    // SAFETY:
    //
    // 指针 `ptr` 刚好在上面构建,并且来自 `try_register_dtor`,它最初是 `self` 的 Key<T>,使其成为非 NUL 且类型正确。
    //
    //
    // 在运行用户析构函数之前,请确保将 `Option<T>` 设置为 `None`,将 `dtor_state` 设置为 `RunningOrHasRun`。
    // 这将导致对 `get` 的 future 调用再次运行 `try_initialize_drop`,该操作现在将失败,并返回 `None`。
    //
    // 将调用包裹在一个 catch 中,以确保在析构函数中发生 panic 时捕获展开。
    //
    //
    //
    //
    if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe {
        let value = (*ptr).inner.take();
        (*ptr).dtor_state.set(DtorState::RunningOrHasRun);
        drop(value);
    })) {
        rtabort!("thread local panicked on drop");
    }
}