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 TAG_MASK: usize = _
pub const TAG_MASK: usize = _
The bitmask for the lower bits available for storing the tag value.
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)
);