Stabilize hint::spin_loop

Partially fix #55002, deprecate in another release

Co-authored-by: Ashley Mannix <kodraus@hey.com>

Update stable version for stabilize_spin_loop

Co-authored-by: Joshua Nelson <joshua@yottadb.com>

Use better example for spinlock

As suggested by KodrAus

Remove renamed_spin_loop already available in master

Fix spin loop example
This commit is contained in:
Ivan Tham
2020-08-30 10:35:50 +08:00
parent 9f6c670c4b
commit e8b5be5dff
4 changed files with 56 additions and 24 deletions

View File

@@ -1,6 +1,7 @@
#![stable(feature = "core_hint", since = "1.27.0")]
//! Hints to compiler that affects how code should be emitted or optimized.
//! Hints may be compile time or runtime.
use crate::intrinsics;
@@ -24,7 +25,6 @@ use crate::intrinsics;
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
/// optimizations but will panic when executed.
///
///
/// # Example
///
/// ```
@@ -51,18 +51,62 @@ pub const unsafe fn unreachable_unchecked() -> ! {
unsafe { intrinsics::unreachable() }
}
/// Emits a machine instruction hinting to the processor that it is running in busy-wait
/// spin-loop ("spin lock").
/// Emits a machine instruction to signal the processor that it is running in
/// a busy-wait spin-loop ("spin lock").
///
/// For a discussion of different locking strategies and their trade-offs, see
/// [`core::sync::atomic::spin_loop_hint`].
/// Upon receiving the spin-loop signal the processor can optimize its behavior by,
/// for example, saving power or switching hyper-threads.
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
/// This function is different from [`thread::yield_now`] which directly
/// yields to the system's scheduler, whereas `spin_loop` does not interact
/// with the operating system.
///
/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint
/// A common use case for `spin_loop` is implementing bounded optimistic
/// spinning in a CAS loop in synchronization primitives. To avoid problems
/// like priority inversion, it is strongly recommended that the spin loop is
/// terminated after a finite amount of iterations and an appropriate blocking
/// syscall is made.
///
/// **Note**: On platforms that do not support receiving spin-loop hints this
/// function does not do anything at all.
///
/// # Examples
///
/// ```
/// use std::sync::atomic::{AtomicBool, Ordering};
/// use std::sync::Arc;
/// use std::{hint, thread};
///
/// // A shared atomic value that threads will use to coordinate
/// let live = Arc::new(AtomicBool::new(false));
///
/// // In a background thread we'll eventually set the value
/// let bg_work = {
/// let live = live.clone();
/// thread::spawn(move || {
/// // Do some work, then make the value live
/// do_some_work();
/// live.store(true, Ordering::Release);
/// })
/// };
///
/// // Back on our current thread, we wait for the value to be set
/// while live.load(Ordering::Acquire) {
/// // The spin loop is a hint to the CPU that we're waiting, but probably
/// // not for very long
/// hint::spin_loop();
/// }
///
/// // The value is now set
/// # 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]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
#[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"))]
{