pub struct TaggedPtr<T> {
pub ptr: Ptr<T>,
pub tag: Tag,
}Expand description
A packaged representation of a pointer and a generation tag.
Used for atomic operations with AtomicTaggedPtr.
Fields§
§ptr: Ptr<T>The physical pointer wrapper.
tag: TagThe generation tag for ABA protection.
Implementations§
Source§impl<T> TaggedPtr<T>
impl<T> TaggedPtr<T>
Sourcepub fn new<P>(ptr: P, tag: Tag) -> Self
pub fn new<P>(ptr: P, tag: Tag) -> Self
Creates a new TaggedPtr from a pointer and a tag.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let val = 42;
let ptr = NonNull::new(&val as *const i32 as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(123));
assert_eq!(tagged.ptr.option(), ptr);
assert_eq!(tagged.tag.value(), 123);Sourcepub const fn null() -> Self
pub const fn null() -> Self
Creates a new TaggedPtr with a null pointer and the default tag.
§Examples
use atomic_tagged_ptr::TaggedPtr;
let p: TaggedPtr<i32> = TaggedPtr::null();
assert!(p.is_null());
assert_eq!(p.tag.value(), 0);Sourcepub fn cast<U>(self) -> TaggedPtr<U>
pub fn cast<U>(self) -> TaggedPtr<U>
Casts the pointer part to a pointer of another type, keeping the tag unchanged.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let val = 42u8;
let tagged = TaggedPtr::new(NonNull::new(&val as *const u8 as *mut u8), Tag::new(123));
let casted: TaggedPtr<i8> = tagged.cast();
assert_eq!(casted.tag.value(), 123);Sourcepub fn decompose(self) -> (Ptr<T>, Tag)
pub fn decompose(self) -> (Ptr<T>, Tag)
Deconstructs the TaggedPtr into a tuple of (Ptr<T>, Tag).
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag, Ptr};
use std::ptr::NonNull;
let val = 42;
let ptr = NonNull::new(&val as *const i32 as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(123));
let (p, t) = tagged.decompose();
assert_eq!(p.option(), ptr);
assert_eq!(t.value(), 123);Sourcepub fn as_ptr(self) -> *const T
pub fn as_ptr(self) -> *const T
Converts the pointer part into a raw const pointer *const T.
Returns a null pointer if the underlying pointer is null.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let val = 42;
let ptr = NonNull::new(&val as *const i32 as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(123));
assert_eq!(unsafe { *tagged.as_ptr() }, 42);
let null_tagged: TaggedPtr<i32> = TaggedPtr::null();
assert!(null_tagged.as_ptr().is_null());Sourcepub fn as_mut_ptr(self) -> *mut T
pub fn as_mut_ptr(self) -> *mut T
Converts the pointer part into a raw mutable pointer *mut T.
Returns a null pointer if the underlying pointer is null.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut val = 42;
let ptr = NonNull::new(&mut val as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(123));
assert_eq!(unsafe { *tagged.as_mut_ptr() }, 42);
let null_tagged: TaggedPtr<i32> = TaggedPtr::null();
assert!(null_tagged.as_mut_ptr().is_null());Sourcepub fn is_null(self) -> bool
pub fn is_null(self) -> bool
Returns true if the pointer part is null.
§Examples
use atomic_tagged_ptr::TaggedPtr;
let p: TaggedPtr<i32> = TaggedPtr::null();
assert!(p.is_null());Sourcepub fn is_some(self) -> bool
pub fn is_some(self) -> bool
Returns true if the pointer part is not null (is some).
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let val = 42;
let p = TaggedPtr::new(NonNull::new(&val as *const i32 as *mut i32), Tag::new(10));
assert!(p.is_some());Sourcepub fn is_none(self) -> bool
pub fn is_none(self) -> bool
Returns true if the pointer part is null (is none).
§Examples
use atomic_tagged_ptr::TaggedPtr;
let p: TaggedPtr<i32> = TaggedPtr::null();
assert!(p.is_none());Sourcepub unsafe fn as_ref<'a>(self) -> Option<&'a T>
pub unsafe fn as_ref<'a>(self) -> Option<&'a T>
Returns a shared reference to the value if the pointer part is not null.
§Safety
The caller must ensure that:
- The pointer is valid (aligned, points to a valid initialized value of type
T). - The memory is not mutated while the reference is active.
- The reference lifetime
'ais correctly bounded.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let val = 42;
let ptr = NonNull::new(&val as *const i32 as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(1));
unsafe {
assert_eq!(tagged.as_ref(), Some(&42));
}Sourcepub unsafe fn as_mut<'a>(self) -> Option<&'a mut T>
pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T>
Returns a mutable reference to the value if the pointer part is not null.
§Safety
The caller must ensure that:
- The pointer is valid (aligned, points to a valid initialized value of type
T). - No other references (shared or mutable) to the same memory are active.
- The reference lifetime
'ais correctly bounded.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut val = 42;
let ptr = NonNull::new(&mut val as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(1));
unsafe {
let r = tagged.as_mut();
assert_eq!(r, Some(&mut 42));
*r.unwrap() = 100;
}
assert_eq!(val, 100);Sourcepub fn with_ptr<U>(self, ptr: impl Into<Ptr<U>>) -> TaggedPtr<U>
pub fn with_ptr<U>(self, ptr: impl Into<Ptr<U>>) -> TaggedPtr<U>
Returns a new TaggedPtr with a different pointer but the same tag.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let val1 = 10;
let val2 = 20;
let ptr1 = NonNull::new(&val1 as *const i32 as *mut i32);
let ptr2 = NonNull::new(&val2 as *const i32 as *mut i32);
let tagged = TaggedPtr::new(ptr1, Tag::new(100));
let new_tagged = tagged.with_ptr(ptr2);
assert_eq!(new_tagged.ptr.option(), ptr2);
assert_eq!(new_tagged.tag.value(), 100);Sourcepub fn with_tag(self, tag: Tag) -> Self
pub fn with_tag(self, tag: Tag) -> Self
Returns a new TaggedPtr with a different tag but the same pointer.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let val = 42;
let ptr = NonNull::new(&val as *const i32 as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(100));
let new_tagged = tagged.with_tag(Tag::new(200));
assert_eq!(new_tagged.ptr.option(), ptr);
assert_eq!(new_tagged.tag.value(), 200);Sourcepub fn map_ptr<U, F>(self, f: F) -> TaggedPtr<U>
pub fn map_ptr<U, F>(self, f: F) -> TaggedPtr<U>
Maps the pointer part of the TaggedPtr using the given closure.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let val = 42u8;
let ptr = NonNull::new(&val as *const u8 as *mut u8);
let tagged = TaggedPtr::new(ptr, Tag::new(100));
let mapped = tagged.map_ptr(|p| p.cast::<i8>());
assert_eq!(unsafe { *mapped.as_ptr() }, 42);
assert_eq!(mapped.tag.value(), 100);Sourcepub unsafe fn read(self) -> T
pub unsafe fn read(self) -> T
Reads the value from the pointer part without moving it. This leaves the memory unchanged.
§Safety
- The pointer must be non-null.
- The pointer must be valid for reads (correctly aligned, points to an initialized instance of
T, etc.). - The memory must not be mutated by another thread while being read.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let val = 42;
let ptr = NonNull::new(&val as *const i32 as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(1));
unsafe {
assert_eq!(tagged.read(), 42);
}Sourcepub unsafe fn read_volatile(self) -> T
pub unsafe fn read_volatile(self) -> T
Performs a volatile read of the value from the pointer part without moving it.
§Safety
- The pointer must be non-null.
- The pointer must be valid for reads.
- The memory must not be mutated by another thread while being read.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let val = 42;
let ptr = NonNull::new(&val as *const i32 as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(1));
unsafe {
assert_eq!(tagged.read_volatile(), 42);
}Sourcepub unsafe fn read_unaligned(self) -> T
pub unsafe fn read_unaligned(self) -> T
Reads the value from the pointer part without moving it, without requiring alignment.
§Safety
- The pointer must be non-null.
- The pointer must be valid for reads.
- The memory must not be mutated by another thread while being read.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let val = 42;
let ptr = NonNull::new(&val as *const i32 as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(1));
unsafe {
assert_eq!(tagged.read_unaligned(), 42);
}Sourcepub unsafe fn write(self, val: T)
pub unsafe fn write(self, val: T)
Overwrites the memory location at the pointer part with the given value.
§Safety
- The pointer must be non-null.
- The pointer must be valid for writes (correctly aligned, etc.).
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut val = 0;
let ptr = NonNull::new(&mut val as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(1));
unsafe {
tagged.write(42);
}
assert_eq!(val, 42);Sourcepub unsafe fn write_volatile(self, val: T)
pub unsafe fn write_volatile(self, val: T)
Performs a volatile write to the memory location at the pointer part.
§Safety
- The pointer must be non-null.
- The pointer must be valid for writes.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut val = 0;
let ptr = NonNull::new(&mut val as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(1));
unsafe {
tagged.write_volatile(42);
}
assert_eq!(val, 42);Sourcepub unsafe fn write_unaligned(self, val: T)
pub unsafe fn write_unaligned(self, val: T)
Overwrites the memory location at the pointer part without requiring alignment.
§Safety
- The pointer must be non-null.
- The pointer must be valid for writes.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut val = 0;
let ptr = NonNull::new(&mut val as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(1));
unsafe {
tagged.write_unaligned(42);
}
assert_eq!(val, 42);Sourcepub unsafe fn replace(self, val: T) -> T
pub unsafe fn replace(self, val: T) -> T
Replaces the value at the pointer part with val, returning the old value.
§Safety
- The pointer must be non-null.
- The pointer must be valid for reads and writes.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut val = 10;
let ptr = NonNull::new(&mut val as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(1));
unsafe {
let old = tagged.replace(20);
assert_eq!(old, 10);
}
assert_eq!(val, 20);Sourcepub unsafe fn swap(self, with: TaggedPtr<T>)
pub unsafe fn swap(self, with: TaggedPtr<T>)
Swaps the values at the pointer part of self and with.
§Safety
- Both pointers must be non-null.
- Both pointers must be valid for reads and writes.
- Both pointers must be properly aligned.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut val1 = 10;
let mut val2 = 20;
let ptr1 = NonNull::new(&mut val1 as *mut i32);
let ptr2 = NonNull::new(&mut val2 as *mut i32);
let tagged1 = TaggedPtr::new(ptr1, Tag::new(1));
let tagged2 = TaggedPtr::new(ptr2, Tag::new(2));
unsafe {
tagged1.swap(tagged2);
}
assert_eq!(val1, 20);
assert_eq!(val2, 10);Sourcepub unsafe fn copy_to(self, dest: TaggedPtr<T>, count: usize)
pub unsafe fn copy_to(self, dest: TaggedPtr<T>, count: usize)
Copies count items from the pointer part of self to dest. The regions may overlap.
§Safety
- Both pointers must be non-null.
- Both pointers must be valid for reads and writes.
- Both pointers must be properly aligned.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut arr = [1, 2, 3];
let ptr1 = NonNull::new(&mut arr[0] as *mut i32);
let ptr2 = NonNull::new(&mut arr[1] as *mut i32);
let tagged1 = TaggedPtr::new(ptr1, Tag::new(1));
let tagged2 = TaggedPtr::new(ptr2, Tag::new(2));
unsafe {
tagged1.copy_to(tagged2, 2);
}
assert_eq!(arr, [1, 1, 2]);Sourcepub unsafe fn copy_to_nonoverlapping(self, dest: TaggedPtr<T>, count: usize)
pub unsafe fn copy_to_nonoverlapping(self, dest: TaggedPtr<T>, count: usize)
Copies count items from the pointer part of self to dest. The regions must not overlap.
§Safety
- Both pointers must be non-null.
- Both pointers must be valid for reads and writes.
- Both pointers must be properly aligned.
- The memory regions must not overlap.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut arr1 = [1, 2, 3];
let mut arr2 = [0, 0, 0];
let ptr1 = NonNull::new(&mut arr1[0] as *mut i32);
let ptr2 = NonNull::new(&mut arr2[0] as *mut i32);
let tagged1 = TaggedPtr::new(ptr1, Tag::new(1));
let tagged2 = TaggedPtr::new(ptr2, Tag::new(2));
unsafe {
tagged1.copy_to_nonoverlapping(tagged2, 3);
}
assert_eq!(arr2, [1, 2, 3]);Sourcepub unsafe fn copy_from(self, src: TaggedPtr<T>, count: usize)
pub unsafe fn copy_from(self, src: TaggedPtr<T>, count: usize)
Copies count items from src to the pointer part of self. The regions may overlap.
§Safety
- Both pointers must be non-null.
- Both pointers must be valid for reads and writes.
- Both pointers must be properly aligned.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut arr = [1, 2, 3];
let ptr1 = NonNull::new(&mut arr[1] as *mut i32);
let ptr2 = NonNull::new(&mut arr[0] as *mut i32);
let tagged1 = TaggedPtr::new(ptr1, Tag::new(1));
let tagged2 = TaggedPtr::new(ptr2, Tag::new(2));
unsafe {
tagged1.copy_from(tagged2, 2);
}
assert_eq!(arr, [1, 1, 2]);Sourcepub unsafe fn copy_from_nonoverlapping(self, src: TaggedPtr<T>, count: usize)
pub unsafe fn copy_from_nonoverlapping(self, src: TaggedPtr<T>, count: usize)
Copies count items from src to the pointer part of self. The regions must not overlap.
§Safety
- Both pointers must be non-null.
- Both pointers must be valid for reads and writes.
- Both pointers must be properly aligned.
- The memory regions must not overlap.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut arr1 = [1, 2, 3];
let mut arr2 = [0, 0, 0];
let ptr1 = NonNull::new(&mut arr2[0] as *mut i32);
let ptr2 = NonNull::new(&mut arr1[0] as *mut i32);
let tagged1 = TaggedPtr::new(ptr1, Tag::new(1));
let tagged2 = TaggedPtr::new(ptr2, Tag::new(2));
unsafe {
tagged1.copy_from_nonoverlapping(tagged2, 3);
}
assert_eq!(arr2, [1, 2, 3]);Sourcepub unsafe fn offset(self, count: isize) -> Self
pub unsafe fn offset(self, count: isize) -> Self
Calculates the offset from the pointer part, returning a new TaggedPtr with the same tag.
§Safety
Both the starting and resulting pointer must be either in bounds or one byte past the end of the same allocated object.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut arr = [10, 20, 30];
let ptr = NonNull::new(&mut arr[0] as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(123));
unsafe {
let offset_tagged = tagged.offset(1);
assert_eq!(offset_tagged.read(), 20);
assert_eq!(offset_tagged.tag.value(), 123);
}Sourcepub unsafe fn add(self, count: usize) -> Self
pub unsafe fn add(self, count: usize) -> Self
Calculates the positive offset from the pointer part, returning a new TaggedPtr with the same tag.
§Safety
Both the starting and resulting pointer must be either in bounds or one byte past the end of the same allocated object.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut arr = [10, 20, 30];
let ptr = NonNull::new(&mut arr[0] as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(123));
unsafe {
let offset_tagged = tagged.add(2);
assert_eq!(offset_tagged.read(), 30);
assert_eq!(offset_tagged.tag.value(), 123);
}Sourcepub unsafe fn sub(self, count: usize) -> Self
pub unsafe fn sub(self, count: usize) -> Self
Calculates the negative offset from the pointer part, returning a new TaggedPtr with the same tag.
§Safety
Both the starting and resulting pointer must be either in bounds or one byte past the end of the same allocated object.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut arr = [10, 20, 30];
let ptr = NonNull::new(&mut arr[2] as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(123));
unsafe {
let offset_tagged = tagged.sub(1);
assert_eq!(offset_tagged.read(), 20);
assert_eq!(offset_tagged.tag.value(), 123);
}Sourcepub fn wrapping_offset(self, count: isize) -> Self
pub fn wrapping_offset(self, count: isize) -> Self
Calculates the wrapping offset from the pointer part, returning a new TaggedPtr with the same tag.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut arr = [10, 20, 30];
let ptr = NonNull::new(&mut arr[0] as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(123));
let offset_tagged = tagged.wrapping_offset(1);
assert_eq!(unsafe { offset_tagged.read() }, 20);
assert_eq!(offset_tagged.tag.value(), 123);Sourcepub fn wrapping_add(self, count: usize) -> Self
pub fn wrapping_add(self, count: usize) -> Self
Calculates the positive wrapping offset from the pointer part, returning a new TaggedPtr with the same tag.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut arr = [10, 20, 30];
let ptr = NonNull::new(&mut arr[0] as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(123));
let offset_tagged = tagged.wrapping_add(2);
assert_eq!(unsafe { offset_tagged.read() }, 30);
assert_eq!(offset_tagged.tag.value(), 123);Sourcepub fn wrapping_sub(self, count: usize) -> Self
pub fn wrapping_sub(self, count: usize) -> Self
Calculates the negative wrapping offset from the pointer part, returning a new TaggedPtr with the same tag.
§Examples
use atomic_tagged_ptr::{TaggedPtr, Tag};
use std::ptr::NonNull;
let mut arr = [10, 20, 30];
let ptr = NonNull::new(&mut arr[2] as *mut i32);
let tagged = TaggedPtr::new(ptr, Tag::new(123));
let offset_tagged = tagged.wrapping_sub(1);
assert_eq!(unsafe { offset_tagged.read() }, 20);
assert_eq!(offset_tagged.tag.value(), 123);