tagptr

Struct AtomicTagPtr

source
pub struct AtomicTagPtr<T, const N: usize> { /* private fields */ }
Expand description

A raw pointer type which can be safely shared between threads and which can use up to N of its lower bits to store additional information (the tag).

This type has the same in-memory representation as a *mut T. It is mostly identical to AtomicPtr, except that all of its methods take or return a TagPtr instead of *mut T. See the crate level documentation for restrictions on the value of N.

Implementations§

source§

impl<T, const N: usize> AtomicTagPtr<T, N>

source

pub const TAG_BITS: usize = N

The number of available tag bits for this type.

source

pub const TAG_MASK: usize = _

The bitmask for the lower bits available for storing the tag value.

source

pub const POINTER_MASK: usize = _

The bitmask for the (higher) bits for storing the pointer itself.

source

pub const fn null() -> Self

Creates a new null pointer.

§Examples
use core::{ptr, sync::atomic::Ordering};

type AtomicTagPtr = tagptr::AtomicTagPtr<i32, 2>;

let ptr = AtomicTagPtr::null();
assert_eq!(
    ptr.load(Ordering::Relaxed).decompose(),
    (ptr::null_mut(), 0)
);
source

pub fn new(marked_ptr: TagPtr<T, N>) -> Self

Creates a new atomic marked pointer.

source

pub fn into_inner(self) -> TagPtr<T, N>

Consumes the atomic marked pointer and returns its contained value.

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

source

pub fn get_mut(&mut self) -> &mut TagPtr<T, N>

Returns a mutable reference to the underlying marked pointer.

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

source

pub fn load(&self, order: Ordering) -> TagPtr<T, N>

Loads the value of the atomic marked pointer.

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.

source

pub fn store(&self, ptr: TagPtr<T, N>, order: Ordering)

Stores a value into the atomic marked pointer.

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.

source

pub fn swap(&self, ptr: TagPtr<T, N>, order: Ordering) -> TagPtr<T, N>

Stores a value into the atomic marked pointer and returns the previous value.

swap takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed, and using Release makes the load part Relaxed.

§Examples
use core::sync::atomic::Ordering;

type AtomicTagPtr = tagptr::AtomicTagPtr<i32, 2>;
type TagPtr = tagptr::TagPtr<i32, 2>;

let ptr = AtomicTagPtr::null();
let prev = ptr.swap(TagPtr::new(&mut 1), Ordering::Relaxed);

assert!(prev.is_null());
source

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

Stores a value into the pointer if the current value is the same as current.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

compare_exchange takes takes two Ordering arguments to describe the memory ordering of this operation. The first describes the required ordering if the operation succeeds while the second describes the required ordering when the operation fails. Using Acquire as success ordering makes store part of this operation Relaxed, and using Release makes the successful load Relaxed. The failure ordering can only be SeqCst, Acquire or Relaxed and must be equivalent or weaker than the success ordering.

source

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

Stores a value into the pointer if the current value is the same as current.

The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to current.

Unlike compare_exchange, this function is allowed to spuriously fail, even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value.

compare_exchange takes takes two Ordering arguments to describe the memory ordering of this operation. The first describes the required ordering if the operation succeeds while the second describes the required ordering when the operation fails. Using Acquire as success ordering makes store part of this operation Relaxed, and using Release makes the successful load Relaxed. The failure ordering can only be SeqCst, Acquire or Relaxed and must be equivalent or weaker than the success ordering.

source

pub fn fetch_add(&self, value: usize, order: Ordering) -> TagPtr<T, N>

Adds value to the current tag value, returning the previous marked pointer.

This operation directly and unconditionally alters the internal numeric representation of the atomic marked pointer. Hence there is no way to reliably guarantee the operation only affects the tag bits and does not overflow into the pointer bits.

fetch_add takes takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed and using Release makes the load part Relaxed.

§Examples
use core::sync::atomic::Ordering;

type AtomicTagPtr = tagptr::AtomicTagPtr<i32, 2>;
type TagPtr = tagptr::TagPtr<i32, 2>;

let reference = &mut 1;
let ptr = AtomicTagPtr::new(TagPtr::new(reference));

assert_eq!(
    ptr.fetch_add(1, Ordering::Relaxed).decompose(),
    (reference as *mut _, 0)
);

assert_eq!(
    ptr.load(Ordering::Relaxed).decompose(),
    (reference as *mut _, 0b01)
);
source

pub fn fetch_sub(&self, value: usize, order: Ordering) -> TagPtr<T, N>

Subtracts value from the current tag value, returning the previous marked pointer.

This operation directly and unconditionally alters the internal numeric representation of the atomic marked pointer. Hence there is no way to reliably guarantee the operation only affects the tag bits and does not overflow into the pointer bits.

fetch_sub takes takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed and using Release makes the load part Relaxed.

§Examples
use core::sync::atomic::Ordering;

type AtomicTagPtr = tagptr::AtomicTagPtr<i32, 2>;
type TagPtr = tagptr::TagPtr<i32, 2>;

let reference = &mut 1;
let ptr = AtomicTagPtr::new(TagPtr::compose(reference, 0b10));

assert_eq!(
    ptr.fetch_sub(1, Ordering::Relaxed).decompose(),
    (reference as *mut _, 0b10)
);

assert_eq!(
    ptr.load(Ordering::Relaxed).decompose(),
    (reference as *mut _, 0b01)
);
source

pub fn fetch_or(&self, value: usize, order: Ordering) -> TagPtr<T, N>

Performs a bitwise “or” of value with the current tag value, returning the previous marked pointer.

This operation directly and unconditionally alters the internal numeric representation of the atomic marked pointer. Hence there is no way to reliably guarantee the operation only affects the tag bits and does not overflow into the pointer bits.

fetch_or takes takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed and using Release makes the load part Relaxed.

§Examples
use core::sync::atomic::Ordering;

type AtomicTagPtr = tagptr::AtomicTagPtr<i32, 2>;
type TagPtr = tagptr::TagPtr<i32, 2>;

let reference = &mut 1;
let ptr = AtomicTagPtr::new(TagPtr::compose(reference, 0b10));

assert_eq!(
    ptr.fetch_or(0b11, Ordering::Relaxed).decompose(),
    (reference as *mut _, 0b10)
);

assert_eq!(
    ptr.load(Ordering::Relaxed).decompose(),
    (reference as *mut _, 0b11)
);
source

pub fn fetch_and(&self, value: usize, order: Ordering) -> TagPtr<T, N>

Performs a bitwise “and” of value with the current tag value, returning the previous marked pointer.

This operation directly and unconditionally alters the internal numeric representation of the atomic marked pointer. Hence there is no way to reliably guarantee the operation only affects the tag bits and does not overflow into the pointer bits.

fetch_and takes takes an Ordering argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using Acquire makes the store part of this operation Relaxed and using Release makes the load part Relaxed.

§Examples
use core::sync::atomic::Ordering;

type AtomicTagPtr = tagptr::AtomicTagPtr<i32, 2>;
type TagPtr = tagptr::TagPtr<i32, 2>;

let reference = &mut 1;
let ptr = AtomicTagPtr::new(TagPtr::compose(reference, 0b10));

// fetch_x returns previous value
assert_eq!(
    ptr.fetch_and(0b11, Ordering::Relaxed).decompose(),
    (reference as *mut _, 0b10)
);

assert_eq!(
    ptr.load(Ordering::Relaxed).decompose(),
    (reference as *mut _, 0b10)
);

Trait Implementations§

source§

impl<T, const N: usize> Debug for AtomicTagPtr<T, N>

source§

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

Formats the value using the given formatter. Read more
source§

impl<T, const N: usize> Default for AtomicTagPtr<T, N>

source§

fn default() -> Self

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

impl<T, const N: usize> From<*mut T> for AtomicTagPtr<T, N>

source§

fn from(ptr: *mut T) -> Self

Converts to this type from the input type.
source§

impl<T, const N: usize> From<TagPtr<T, N>> for AtomicTagPtr<T, N>

source§

fn from(ptr: TagPtr<T, N>) -> Self

Converts to this type from the input type.
source§

impl<T, const N: usize> Pointer for AtomicTagPtr<T, N>

source§

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

Formats the value using the given formatter. Read more
source§

impl<T, const N: usize> Send for AtomicTagPtr<T, N>

source§

impl<T, const N: usize> Sync for AtomicTagPtr<T, N>

Auto Trait Implementations§

§

impl<T, const N: usize> !Freeze for AtomicTagPtr<T, N>

§

impl<T, const N: usize> RefUnwindSafe for AtomicTagPtr<T, N>
where T: RefUnwindSafe,

§

impl<T, const N: usize> Unpin for AtomicTagPtr<T, N>

§

impl<T, const N: usize> UnwindSafe for AtomicTagPtr<T, N>
where T: RefUnwindSafe,

Blanket Implementations§

source§

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

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

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

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

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

source§

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

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

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

source§

fn into(self) -> U

Calls U::from(self).

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

source§

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

source§

type Error = Infallible

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

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

Performs the conversion.
source§

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

source§

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

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

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

Performs the conversion.