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
#![stable(feature = "core_hint", since = "1.27.0")]

//! 对编译器的提示,该提示会影响应如何发出或优化代码。
//! 提示可能是编译时或运行时。

use crate::intrinsics;

/// 通知编译器代码中的这一点不可访问,从而可以进行进一步的优化。
///
/// # Safety
///
/// 达到此函数完全是 *未定义的行为* (UB)。特别是,编译器假定所有 UB 都绝不会发生,因此将消除到达 `unreachable_unchecked()` 调用的所有分支。
///
/// 与 UB 的所有实例一样,如果这种假设被证明是错误的,即 `unreachable_unchecked()` 调用实际上在所有可能的控制流中都是可以到达的,则编译器将应用错误的优化策略,有时甚至可能破坏看似无关的代码,从而导致难以解决的问题 - 调试问题。
///
///
/// 仅当您可以证明该代码永远不会调用它时,才使用此函数。
/// 否则,请考虑使用 [`unreachable!`] 宏,该宏不允许进行优化,但是在执行时将为 panic。
///
/// # Example
///
/// ```
/// fn div_1(a: u32, b: u32) -> u32 {
///     use std::hint::unreachable_unchecked;
///
///     // `b.saturating_add(1)` 始终为正 (不为零),因此 `checked_div` 将永远不会返回 `None`。
/////
///     // 因此,else 分支不可访问。
///     a.checked_div(b.saturating_add(1))
///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
/// }
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
/// assert_eq!(div_1(11, u32::MAX), 0);
/// ```
///
///
///
///
///
///
///
///
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
pub const unsafe fn unreachable_unchecked() -> ! {
    // SAFETY: 调用者必须遵守 `intrinsics::unreachable` 的安全保证。
    //
    unsafe { intrinsics::unreachable() }
}

/// 发出一条机器指令,以向处理器发送信号,指示其正在忙于等待的自旋循环 (自旋锁) 中运行。
///
/// 在接收到自旋环信号后,处理器可以通过例如节省功率或切换 hyper 线程来优化其行为。
///
/// 此函数不同于 [`thread::yield_now`],后者直接产生系统的调度程序,而 `spin_loop` 不与操作系统交互。
///
/// `spin_loop` 的一个常见用例是在同步原语的 CAS 循环中实现有界乐观旋转。
/// 为避免优先级倒置之类的问题,强烈建议在有限次数的迭代后终止旋转循环,并进行适当的阻塞系统调用。
///
///
/// **Note**: 在不支持接收自旋循环提示的平台上,此函数完全不执行任何操作。
///
/// # Examples
///
/// ```
/// use std::sync::atomic::{AtomicBool, Ordering};
/// use std::sync::Arc;
/// use std::{hint, thread};
///
/// // 线程将用于协调的共享原子值
/// let live = Arc::new(AtomicBool::new(false));
///
/// // 在后台线程中,我们最终将设置该值
/// let bg_work = {
///     let live = live.clone();
///     thread::spawn(move || {
///         // 做一些工作,然后创造值
///         do_some_work();
///         live.store(true, Ordering::Release);
///     })
/// };
///
/// // 回到我们当前的线程,我们等待该值被设置
/// while !live.load(Ordering::Acquire) {
///     // 自旋循环是对我们正在等待的 CPU 的提示,但可能不会持续很长时间
/////
///     hint::spin_loop();
/// }
///
/// // 现在设置该值
/// # fn do_some_work() {}
/// do_some_work();
/// bg_work.join()?;
/// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(())
/// ```
///
/// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html
///
///
///
///
///
///
///
#[inline]
#[stable(feature = "renamed_spin_loop", since = "1.49.0")]
pub fn spin_loop() {
    #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
    {
        #[cfg(target_arch = "x86")]
        {
            // SAFETY: `cfg` 属性确保我们仅在 x86 目标上执行此操作。
            unsafe { crate::arch::x86::_mm_pause() };
        }

        #[cfg(target_arch = "x86_64")]
        {
            // SAFETY: `cfg` 属性确保我们仅在 x86_64 目标上执行此操作。
            unsafe { crate::arch::x86_64::_mm_pause() };
        }
    }

    #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
    {
        #[cfg(target_arch = "aarch64")]
        {
            // SAFETY: `cfg` 属性确保我们仅在 aarch64 目标上执行此操作。
            unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) };
        }
        #[cfg(target_arch = "arm")]
        {
            // SAFETY: `cfg` 属性确保我们仅在支持 v6 功能的 arm 目标上执行此操作。
            //
            unsafe { crate::arch::arm::__yield() };
        }
    }
}

/// *__提示 __* 到编译器的标识函数,对于 `black_box` 可以做什么最大程度地悲观。
///
/// 与 [`std::convert::identity`] 不同,鼓励 Rust 编译器假定 `black_box` 可以以允许 Rust 代码使用的任何可能有效方式使用 `dummy`,而不会在调用代码中引入未定义的行为。
///
/// 此属性使 `black_box` 可用于编写不需要进行某些优化 (例如基准测试) 的代码。
///
/// 但是请注意,`black_box` 仅 (并且只能) 以 "best-effort" 为基础提供。它可以阻止优化的程度可能会有所不同,具体取决于所使用的平台和代码源后端。
/// 程序不能以任何方式依靠 `black_box` 的正确性。
///
/// [`std::convert::identity`]: crate::convert::identity
///
///
///
#[cfg_attr(not(miri), inline)]
#[cfg_attr(miri, inline(never))]
#[unstable(feature = "bench_black_box", issue = "64102")]
#[cfg_attr(miri, allow(unused_mut))]
pub fn black_box<T>(mut dummy: T) -> T {
    // 我们需要以某种方式 "use" LLVM 无法自省该参数,并且在支持它的目标上,我们通常可以利用内联汇编来执行此操作。
    // LLVM 对内联汇编的解释是,它是黑色的 box。
    // 这不是最好的实现,因为它可能对优化进行的优化超出了我们的期望,但到目前为止已经足够好了。
    //
    //

    #[cfg(not(miri))] // 这只是一个提示,因此可以跳过 Miri。
    // SAFETY: 内联汇编是无操作的。
    unsafe {
        // FIXME: 无法使用 `asm!`,因为它不支持 MIPS 和其他体系结构。
        llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
    }

    dummy
}