Struct std::sync::atomic::AtomicU8

1.34.0 · source ·
#[repr(C, align(1))]
pub struct AtomicU8 { /* private fields */ }
Expand description

可以在线程之间安全共享的整数类型。

此类型与基本整数类型 [` 具有相同的内存表示形式

u8 `]. 有关原子类型和非原子类型之间的区别以及有关此类型的可移植性的更多信息,请参见 模块级文档

Note: 此类型仅在支持原子负载和 [` 的存储的平台上可用

u8 `].

Implementations§

source§

impl AtomicU8

const: 1.34.0 · source

pub const fn new(v: u8) -> AtomicU8

创建一个新的原子整数。

Examples
use std::sync::atomic::AtomicU8;

let atomic_forty_two = AtomicU8::new(42);
Run
const: unstable · source

pub unsafe fn from_ptr<'a>(ptr: *mut u8) -> &'a AtomicU8

🔬This is a nightly-only experimental API. (atomic_from_ptr #108652)

从指针创建一个新的引用到原子整数。

Examples
#![feature(atomic_from_ptr, pointer_is_aligned)]
use std::sync::atomic::{self, AtomicU8};
use std::mem::align_of;

// 获取指向分配值的指针
let ptr: *mut u8 = Box::into_raw(Box::new(0));

assert!(ptr.is_aligned_to(align_of::<AtomicU8>()));

{
    // 创建分配值的原子视图
    let atomic = unsafe {AtomicU8::from_ptr(ptr) };

    // 使用 `atomic` 进行原子操作,可能与其他线程共享
    atomic.store(1, atomic::Ordering::Relaxed);
}

// 可以非原子地访问 `ptr` 后面的值,因为对原子的引用在上面的块中结束了它的生命周期
assert_eq!(unsafe { *ptr }, 1);

// 释放值
unsafe { drop(Box::from_raw(ptr)) }
Run
Safety
  • ptr 必须与 align_of::<AtomicBool>() 对齐 (请注意,在某些平台上,它可能比 align_of::<bool>() 大)。
  • ptr must be aligned to align_of::<AtomicU8>() (note that on some platforms this can be bigger than align_of::<u8>()).
  • 对于整个生命周 'a 的读取和写入,ptr 必须是 valid
  • 整个生命周 'a 都不能通过非原子操作访问到 ptr 后面的值。
source

pub fn get_mut(&mut self) -> &mut u8

返回底层整数的可变引用。

这是安全的,因为可变引用保证没有其他线程同时访问原子数据。

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let mut some_var = AtomicU8::new(10);
assert_eq!(*some_var.get_mut(), 10);
*some_var.get_mut() = 5;
assert_eq!(some_var.load(Ordering::SeqCst), 5);
Run
source

pub fn from_mut(v: &mut u8) -> &mut AtomicU8

🔬This is a nightly-only experimental API. (atomic_from_mut #76314)

Get atomic access to a &mut u8.

Examples
#![feature(atomic_from_mut)]
use std::sync::atomic::{AtomicU8, Ordering};

let mut some_int = 123;
let a = AtomicU8::from_mut(&mut some_int);
a.store(100, Ordering::Relaxed);
assert_eq!(some_int, 100);
Run
source

pub fn get_mut_slice(this: &mut [AtomicU8]) -> &mut [u8]

🔬This is a nightly-only experimental API. (atomic_from_mut #76314)

Get non-atomic access to a &mut [AtomicU8] slice 这是安全的,因为可变引用保证没有其他线程同时访问原子数据。

Examples
#![feature(atomic_from_mut, inline_const)]
use std::sync::atomic::{AtomicU8, Ordering};

let mut some_ints = [const { AtomicU8::new(0) }; 10];

let view: &mut [u8] = AtomicU8::get_mut_slice(&mut some_ints);
assert_eq!(view, [0; 10]);
view
    .iter_mut()
    .enumerate()
    .for_each(|(idx, int)| *int = idx as _);

std::thread::scope(|s| {
    some_ints
        .iter()
        .enumerate()
        .for_each(|(idx, int)| {
            s.spawn(move || assert_eq!(int.load(Ordering::Relaxed), idx as _));
        })
});
Run
source

pub fn from_mut_slice(v: &mut [u8]) -> &mut [AtomicU8]

🔬This is a nightly-only experimental API. (atomic_from_mut #76314)

Get atomic access to a &mut [u8] slice.

Examples
#![feature(atomic_from_mut)]
use std::sync::atomic::{AtomicU8, Ordering};

let mut some_ints = [0; 10];
let a = &*AtomicU8::from_mut_slice(&mut some_ints);
std::thread::scope(|s| {
    for i in 0..a.len() {
        s.spawn(move || a[i].store(i as _, Ordering::Relaxed));
    }
});
for (i, n) in some_ints.into_iter().enumerate() {
    assert_eq!(i, n as usize);
}
Run
const: unstable · source

pub fn into_inner(self) -> u8

消耗原子并返回包含的值。

这是安全的,因为按值传递 self 可以确保没有其他线程同时访问原子数据。

Examples
use std::sync::atomic::AtomicU8;

let some_var = AtomicU8::new(5);
assert_eq!(some_var.into_inner(), 5);
Run
source

pub fn load(&self, order: Ordering) -> u8

从原子整数加载值。

load 需要一个 Ordering 参数,它描述了这个操作的内存顺序。 可能的值为 SeqCstAcquireRelaxed

Panics

如果 orderReleaseAcqRel,就会出现 panics。

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let some_var = AtomicU8::new(5);

assert_eq!(some_var.load(Ordering::Relaxed), 5);
Run
source

pub fn store(&self, val: u8, order: Ordering)

将值存储到原子整数中。

store 需要一个 Ordering 参数,它描述了这个操作的内存顺序。 可能的值为 SeqCstReleaseRelaxed

Panics

如果 orderAcquireAcqRel,就会出现 panics。

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let some_var = AtomicU8::new(5);

some_var.store(10, Ordering::Relaxed);
assert_eq!(some_var.load(Ordering::Relaxed), 10);
Run
source

pub fn swap(&self, val: u8, order: Ordering) -> u8

将值存储到原子整数中,返回前一个值。

swap 需要一个 Ordering 参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。 请注意,使用 Acquire 会使该操作成为存储部分 Relaxed,而使用 Release 会使装入部分成为 Relaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let some_var = AtomicU8::new(5);

assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
Run
source

pub fn compare_and_swap(&self, current: u8, new: u8, order: Ordering) -> u8

👎Deprecated since 1.50.0: Use compare_exchange or compare_exchange_weak instead

如果当前值与 current 值相同,则将值存储到原子整数中。

返回值始终是前一个值。如果等于 current,则该值已更新。

compare_and_swap 还带有一个 Ordering 参数,它描述了此操作的内存顺序。 请注意,即使使用 AcqRel,该操作也可能失败,因此仅执行 Acquire 加载,但没有 Release 语义。

如果发生此操作,则使用 Acquire 使其成为该操作 Relaxed 的存储部分,而使用 Release 使该操作成为存储部分 Relaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

迁移到 compare_exchangecompare_exchange_weak

compare_and_swap 等效于 compare_exchange,具有以下内存排序映射:

OriginalSuccessFailure
RelaxedRelaxedRelaxed Acquire

即使比较成功,compare_exchange_weak 也允许虚假失败,这允许编译器在循环中使用比较和交换时生成更好的汇编代码。

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let some_var = AtomicU8::new(5);

assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
assert_eq!(some_var.load(Ordering::Relaxed), 10);

assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
assert_eq!(some_var.load(Ordering::Relaxed), 10);
Run
source

pub fn compare_exchange( &self, current: u8, new: u8, success: Ordering, failure: Ordering ) -> Result<u8, u8>

如果当前值与 current 值相同,则将值存储到原子整数中。

返回值是指示是否写入了新值并包含先前值的结果。 成功后,此值保证等于 current

compare_exchange 需要两个 Ordering 参数来描述这个操作的内存顺序。 success 描述了在与 current 的比较成功时发生的读取 - 修改 - 写入操作所需的顺序。 failure 描述了比较失败时发生的加载操作所需的排序。 使用 Acquire 作为成功排序,使存储成为操作 Relaxed 的一部分,而使用 Release,则使装载成功 Relaxed

故障顺序只能是 SeqCstAcquireRelaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let some_var = AtomicU8::new(5);

assert_eq!(some_var.compare_exchange(5, 10,
                                     Ordering::Acquire,
                                     Ordering::Relaxed),
           Ok(5));
assert_eq!(some_var.load(Ordering::Relaxed), 10);

assert_eq!(some_var.compare_exchange(6, 12,
                                     Ordering::SeqCst,
                                     Ordering::Acquire),
           Err(10));
assert_eq!(some_var.load(Ordering::Relaxed), 10);
Run
source

pub fn compare_exchange_weak( &self, current: u8, new: u8, success: Ordering, failure: Ordering ) -> Result<u8, u8>

如果当前值与 current 值相同,则将值存储到原子整数中。

Unlike AtomicU8::compare_exchange, 即使比较成功,此函数也可能会虚假地失败,这可能导致某些平台上的代码效率更高。 返回值是指示是否写入了新值并包含先前值的结果。

compare_exchange_weak 需要两个 Ordering 参数来描述这个操作的内存顺序。 success 描述了在与 current 的比较成功时发生的读取 - 修改 - 写入操作所需的顺序。 failure 描述了比较失败时发生的加载操作所需的排序。 使用 Acquire 作为成功排序,使存储成为操作 Relaxed 的一部分,而使用 Release,则使装载成功 Relaxed

故障顺序只能是 SeqCstAcquireRelaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let val = AtomicU8::new(4);

let mut old = val.load(Ordering::Relaxed);
loop {
    let new = old * 2;
    match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
        Ok(_) => break,
        Err(x) => old = x,
    }
}
Run
source

pub fn fetch_add(&self, val: u8, order: Ordering) -> u8

加到当前值,返回前一个值。

此操作在溢出时回绕。

fetch_add 需要一个 Ordering 参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。 请注意,使用 Acquire 会使该操作成为存储部分 Relaxed,而使用 Release 会使装入部分成为 Relaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let foo = AtomicU8::new(0);
assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
assert_eq!(foo.load(Ordering::SeqCst), 10);
Run
source

pub fn fetch_sub(&self, val: u8, order: Ordering) -> u8

从当前值中减去,返回前一个值。

此操作在溢出时回绕。

fetch_sub 需要一个 Ordering 参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。 请注意,使用 Acquire 会使该操作成为存储部分 Relaxed,而使用 Release 会使装入部分成为 Relaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let foo = AtomicU8::new(20);
assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
assert_eq!(foo.load(Ordering::SeqCst), 10);
Run
source

pub fn fetch_and(&self, val: u8, order: Ordering) -> u8

“and” 按位与当前值。

对当前值和参数 val 执行按位 “and” 运算,并将新值设置为结果。

返回前一个值。

fetch_and 需要一个 Ordering 参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。 请注意,使用 Acquire 会使该操作成为存储部分 Relaxed,而使用 Release 会使装入部分成为 Relaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let foo = AtomicU8::new(0b101101);
assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
Run
source

pub fn fetch_nand(&self, val: u8, order: Ordering) -> u8

“nand” 按位与当前值。

对当前值和参数 val 执行按位 “nand” 运算,并将新值设置为结果。

返回前一个值。

fetch_nand 需要一个 Ordering 参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。 请注意,使用 Acquire 会使该操作成为存储部分 Relaxed,而使用 Release 会使装入部分成为 Relaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let foo = AtomicU8::new(0x13);
assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
Run
source

pub fn fetch_or(&self, val: u8, order: Ordering) -> u8

“or” 按位与当前值。

对当前值和参数 val 执行按位 “or” 运算,并将新值设置为结果。

返回前一个值。

fetch_or 需要一个 Ordering 参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。 请注意,使用 Acquire 会使该操作成为存储部分 Relaxed,而使用 Release 会使装入部分成为 Relaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let foo = AtomicU8::new(0b101101);
assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
Run
source

pub fn fetch_xor(&self, val: u8, order: Ordering) -> u8

“xor” 按位与当前值。

对当前值和参数 val 执行按位 “xor” 运算,并将新值设置为结果。

返回前一个值。

fetch_xor 需要一个 Ordering 参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。 请注意,使用 Acquire 会使该操作成为存储部分 Relaxed,而使用 Release 会使装入部分成为 Relaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let foo = AtomicU8::new(0b101101);
assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
Run
1.45.0 · source

pub fn fetch_update<F>( &self, set_order: Ordering, fetch_order: Ordering, f: F ) -> Result<u8, u8>where F: FnMut(u8) -> Option<u8>,

获取该值,并对其应用一个函数,该函数返回一个可选的新值。如果函数返回 Some(_),则返回 Ok(previous_value)Result,否则返回 Err(previous_value)

Note: 如果与此同时从其他线程更改了值,则只要函数返回 Some(_),这可能会多次调用该函数,但是该函数仅对存储的值应用一次。

fetch_update 需要两个 Ordering 参数来描述这个操作的内存顺序。 第一个描述了操作最终成功时所需的顺序,第二个描述了负载所需的顺序。这些对应于成功和失败的顺序

AtomicU8::compare_exchange respectively.

使用 Acquire 作为成功排序,使存储成为该操作 Relaxed 的一部分,而使用 Release,则使最终成功加载 Relaxed。 (failed) 加载顺序只能是 SeqCstAcquireRelaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Considerations

这种方法并不神奇; 它不是由硬件提供的。 它是按照以下方式实现的 AtomicU8::compare_exchange_weak, 并遭受同样的缺点。 特别是,这种方法不会绕过 ABA Problem

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let x = AtomicU8::new(7);
assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
assert_eq!(x.load(Ordering::SeqCst), 9);
Run
1.45.0 · source

pub fn fetch_max(&self, val: u8, order: Ordering) -> u8

当前值的最大值。

查找当前值和参数 val 的最大值,并将新值设置为结果。

返回前一个值。

fetch_max 需要一个 Ordering 参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。 请注意,使用 Acquire 会使该操作成为存储部分 Relaxed,而使用 Release 会使装入部分成为 Relaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let foo = AtomicU8::new(23);
assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
assert_eq!(foo.load(Ordering::SeqCst), 42);
Run

如果要一步获得最大值,可以使用以下方法:

use std::sync::atomic::{AtomicU8, Ordering};

let foo = AtomicU8::new(23);
let bar = 42;
let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
assert!(max_foo == 42);
Run
1.45.0 · source

pub fn fetch_min(&self, val: u8, order: Ordering) -> u8

当前值的最小值。

查找当前值和参数 val 的最小值,并将新值设置为结果。

返回前一个值。

fetch_min 需要一个 Ordering 参数,它描述了这个操作的内存顺序。所有排序模式都是可能的。 请注意,使用 Acquire 会使该操作成为存储部分 Relaxed,而使用 Release 会使装入部分成为 Relaxed

Note: 此方法仅在支持原子操作的平台上可用

u8.

Examples
use std::sync::atomic::{AtomicU8, Ordering};

let foo = AtomicU8::new(23);
assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
assert_eq!(foo.load(Ordering::Relaxed), 23);
assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
assert_eq!(foo.load(Ordering::Relaxed), 22);
Run

如果要一步获得最小值,则可以使用以下方法:

use std::sync::atomic::{AtomicU8, Ordering};

let foo = AtomicU8::new(23);
let bar = 12;
let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
assert_eq!(min_foo, 12);
Run
1.70.0 (const: 1.70.0) · source

pub const fn as_ptr(&self) -> *mut u8

返回指向底层整数的可变指针。

在结果整数上进行非原子读取和写入可以是数据竞争。 此方法对于 FFI 最为有用,在 FFI 中可能使用函数签名 *mut u8 instead of &AtomicU8. 从共享引用返回 *mut 指针到此原子是安全的,因为原子类型可与内部可变性一起使用。 原子的所有修改都通过共享的 quot 更改值,并且只要它们使用原子操作就可以安全地进行更改。 对返回的裸指针的任何使用都需要一个 unsafe 块,并且仍然必须遵守相同的限制:对其进行的操作必须是原子的。

Examples
use std::sync::atomic::AtomicU8;

extern "C" {
    fn my_atomic_op(arg: *mut u8);
}

let atomic = AtomicU8::new(1);

// SAFETY: 只要 `my_atomic_op` 是原子的就安全。
unsafe {
    my_atomic_op(atomic.as_ptr());
}
Run

Trait Implementations§

source§

impl Debug for AtomicU8

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

使用给定的格式化程序格式化该值。 Read more
source§

impl Default for AtomicU8

source§

fn default() -> AtomicU8

返回类型的 “默认值”。 Read more
source§

impl From<u8> for AtomicU8

source§

fn from(v: u8) -> AtomicU8

Converts an u8 into an AtomicU8.

source§

impl RefUnwindSafe for AtomicU8

source§

impl Sync for AtomicU8

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

获取 selfTypeIdRead more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

从拥有的值中一成不变地借用。 Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

从拥有的值中借用。 Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

返回未更改的参数。

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

调用 U::from(self)

也就是说,这种转换是 From<T> for U 实现选择执行的任何操作。

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

发生转换错误时返回的类型。
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

执行转换。
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

发生转换错误时返回的类型。
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

执行转换。