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>
impl<T, const N: usize> AtomicTagPtr<T, N>
Sourcepub const POINTER_MASK: usize
pub const POINTER_MASK: usize
The bitmask for the (higher) bits for storing the pointer itself.
Sourcepub const fn null() -> Self
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)
);Sourcepub fn into_inner(self) -> TagPtr<T, N>
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.
Sourcepub fn get_mut(&mut self) -> &mut TagPtr<T, N>
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.
Sourcepub fn swap(&self, ptr: TagPtr<T, N>, order: Ordering) -> TagPtr<T, N>
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());Sourcepub fn compare_exchange(
&self,
current: TagPtr<T, N>,
new: TagPtr<T, N>,
(success, failure): (Ordering, Ordering),
) -> Result<TagPtr<T, N>, TagPtr<T, N>>
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.
Sourcepub fn compare_exchange_weak(
&self,
current: TagPtr<T, N>,
new: TagPtr<T, N>,
(success, failure): (Ordering, Ordering),
) -> Result<TagPtr<T, N>, TagPtr<T, N>>
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.
Sourcepub fn fetch_add(&self, value: usize, order: Ordering) -> TagPtr<T, N>
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)
);Sourcepub fn fetch_sub(&self, value: usize, order: Ordering) -> TagPtr<T, N>
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)
);Sourcepub fn fetch_or(&self, value: usize, order: Ordering) -> TagPtr<T, N>
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)
);Sourcepub fn fetch_and(&self, value: usize, order: Ordering) -> TagPtr<T, N>
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)
);