1
1
#![ stable( feature = "core_hint" , since = "1.27.0" ) ]
2
2
3
3
//! Hints to compiler that affects how code should be emitted or optimized.
4
+ //! Hints may be compile time or runtime.
4
5
5
6
use crate :: intrinsics;
6
7
@@ -24,7 +25,6 @@ use crate::intrinsics;
24
25
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
25
26
/// optimizations but will panic when executed.
26
27
///
27
- ///
28
28
/// # Example
29
29
///
30
30
/// ```
@@ -51,18 +51,62 @@ pub const unsafe fn unreachable_unchecked() -> ! {
51
51
unsafe { intrinsics:: unreachable ( ) }
52
52
}
53
53
54
- /// Emits a machine instruction hinting to the processor that it is running in busy-wait
55
- /// spin-loop ("spin lock").
54
+ /// Emits a machine instruction to signal the processor that it is running in
55
+ /// a busy-wait spin-loop ("spin lock").
56
+ ///
57
+ /// Upon receiving the spin-loop signal the processor can optimize its behavior by,
58
+ /// for example, saving power or switching hyper-threads.
59
+ ///
60
+ /// This function is different from [`thread::yield_now`] which directly
61
+ /// yields to the system's scheduler, whereas `spin_loop` does not interact
62
+ /// with the operating system.
63
+ ///
64
+ /// A common use case for `spin_loop` is implementing bounded optimistic
65
+ /// spinning in a CAS loop in synchronization primitives. To avoid problems
66
+ /// like priority inversion, it is strongly recommended that the spin loop is
67
+ /// terminated after a finite amount of iterations and an appropriate blocking
68
+ /// syscall is made.
69
+ ///
70
+ /// **Note**: On platforms that do not support receiving spin-loop hints this
71
+ /// function does not do anything at all.
72
+ ///
73
+ /// # Examples
56
74
///
57
- /// For a discussion of different locking strategies and their trade-offs, see
58
- /// [`core::sync::atomic::spin_loop_hint`].
75
+ /// ```
76
+ /// use std::sync::atomic::{AtomicBool, Ordering};
77
+ /// use std::sync::Arc;
78
+ /// use std::{hint, thread};
79
+ ///
80
+ /// // A shared atomic value that threads will use to coordinate
81
+ /// let live = Arc::new(AtomicBool::new(false));
82
+ ///
83
+ /// // In a background thread we'll eventually set the value
84
+ /// let bg_work = {
85
+ /// let live = live.clone();
86
+ /// thread::spawn(move || {
87
+ /// // Do some work, then make the value live
88
+ /// do_some_work();
89
+ /// live.store(true, Ordering::Release);
90
+ /// })
91
+ /// };
59
92
///
60
- /// **Note**: On platforms that do not support receiving spin-loop hints this function does not
61
- /// do anything at all.
93
+ /// // Back on our current thread, we wait for the value to be set
94
+ /// while live.load(Ordering::Acquire) {
95
+ /// // The spin loop is a hint to the CPU that we're waiting, but probably
96
+ /// // not for very long
97
+ /// hint::spin_loop();
98
+ /// }
99
+ ///
100
+ /// // The value is now set
101
+ /// # fn do_some_work() {}
102
+ /// do_some_work();
103
+ /// bg_work.join()?;
104
+ /// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(())
105
+ /// ```
62
106
///
63
- /// [`core::sync::atomic::spin_loop_hint `]: crate::sync::atomic::spin_loop_hint
107
+ /// [`thread::yield_now `]: ../../std/thread/fn.yield_now.html
64
108
#[ inline]
65
- #[ unstable ( feature = "renamed_spin_loop" , issue = "55002 " ) ]
109
+ #[ stable ( feature = "renamed_spin_loop" , since = "1.49.0 " ) ]
66
110
pub fn spin_loop ( ) {
67
111
#[ cfg( all( any( target_arch = "x86" , target_arch = "x86_64" ) , target_feature = "sse2" ) ) ]
68
112
{
0 commit comments