Struct atomic_polyfill::AtomicI8

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

An integer type which can be safely shared between threads.

This type has the same in-memory representation as the underlying integer type, [i8]. For more about the differences between atomic types and non-atomic types as well as information about the portability of this type, please see the module-level documentation.

Note: This type is only available on platforms that support atomic loads and stores of [i8].

Implementations§

§

impl AtomicI8

const: 1.34.0

pub const fn new(v: i8) -> AtomicI8

Creates a new atomic integer.

Examples
use std::sync::atomic::AtomicI8;

let atomic_forty_two = AtomicI8::new(42);
const: unstable

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

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

Creates a new reference to an atomic integer from a pointer.

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

// Get a pointer to an allocated value
let ptr: *mut i8 = Box::into_raw(Box::new(0));

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

{
    // Create an atomic view of the allocated value
    let atomic = unsafe {AtomicI8::from_ptr(ptr) };

    // Use `atomic` for atomic operations, possibly share it with other threads
    atomic.store(1, atomic::Ordering::Relaxed);
}

// It's ok to non-atomically access the value behind `ptr`,
// since the reference to the atomic ended its lifetime in the block above
assert_eq!(unsafe { *ptr }, 1);

// Deallocate the value
unsafe { drop(Box::from_raw(ptr)) }
Safety
  • ptr must be aligned to align_of::<AtomicBool>() (note that on some platforms this can be bigger than align_of::<bool>()).
  • ptr must be aligned to align_of::<AtomicI8>() (note that on some platforms this can be bigger than align_of::<i8>()).
  • ptr must be valid for both reads and writes for the whole lifetime 'a.
  • The value behind ptr must not be accessed through non-atomic operations for the whole lifetime 'a.

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

Returns a mutable reference to the underlying integer.

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

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

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

pub fn from_mut(v: &mut i8) -> &mut AtomicI8

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

Get atomic access to a &mut i8.

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

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

pub fn get_mut_slice(this: &mut [AtomicI8]) -> &mut [i8]

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

Get non-atomic access to a &mut [AtomicI8] slice

This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data.

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

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

let view: &mut [i8] = AtomicI8::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 _));
        })
});

pub fn from_mut_slice(v: &mut [i8]) -> &mut [AtomicI8]

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

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

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

let mut some_ints = [0; 10];
let a = &*AtomicI8::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);
}
const: unstable

pub fn into_inner(self) -> i8

Consumes the atomic and returns the contained value.

This is safe because passing self by value guarantees that no other threads are concurrently accessing the atomic data.

Examples
use std::sync::atomic::AtomicI8;

let some_var = AtomicI8::new(5);
assert_eq!(some_var.into_inner(), 5);

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

Loads a value from the atomic integer.

load takes an Ordering argument which describes the memory ordering of this operation. Possible values are SeqCst, Acquire and Relaxed.

Panics

Panics if order is Release or AcqRel.

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

let some_var = AtomicI8::new(5);

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

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

Stores a value into the atomic integer.

store takes an Ordering argument which describes the memory ordering of this operation. Possible values are SeqCst, Release and Relaxed.

Panics

Panics if order is Acquire or AcqRel.

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

let some_var = AtomicI8::new(5);

some_var.store(10, Ordering::Relaxed);
assert_eq!(some_var.load(Ordering::Relaxed), 10);
1.70.0 (const: 1.70.0)

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

Returns a mutable pointer to the underlying integer.

Doing non-atomic reads and writes on the resulting integer can be a data race. This method is mostly useful for FFI, where the function signature may use *mut i8 instead of &AtomicI8.

Returning an *mut pointer from a shared reference to this atomic is safe because the atomic types work with interior mutability. All modifications of an atomic change the value through a shared reference, and can do so safely as long as they use atomic operations. Any use of the returned raw pointer requires an unsafe block and still has to uphold the same restriction: operations on it must be atomic.

Examples
use std::sync::atomic::AtomicI8;

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

let atomic = AtomicI8::new(1);

// SAFETY: Safe as long as `my_atomic_op` is atomic.
unsafe {
    my_atomic_op(atomic.as_ptr());
}

Trait Implementations§

§

impl Debug for AtomicI8

§

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

Formats the value using the given formatter. Read more
§

impl Default for AtomicI8

§

fn default() -> AtomicI8

Returns the “default value” for a type. Read more
§

impl From<i8> for AtomicI8

§

fn from(v: i8) -> AtomicI8

Converts an i8 into an AtomicI8.

§

impl RefUnwindSafe for AtomicI8

§

impl Sync for AtomicI8

Auto Trait Implementations§

§

impl Send for AtomicI8

§

impl Unpin for AtomicI8

§

impl UnwindSafe for AtomicI8

Blanket Implementations§

§

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

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

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

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

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

§

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

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

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

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

§

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

§

type Error = Infallible

The type returned in the event of a conversion error.
§

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

Performs the conversion.
§

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

§

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

The type returned in the event of a conversion error.
§

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

Performs the conversion.