pub struct VolatilePtr<'a, T, A = ReadWrite>where
T: ?Sized,{ /* private fields */ }
Expand description
Wraps a pointer to make accesses to the referenced value volatile.
Allows volatile reads and writes on the referenced value. The referenced value needs to
be Copy
for reading and writing, as volatile reads and writes take and return copies
of the value.
Since not all volatile resources (e.g. memory mapped device registers) are both readable
and writable, this type supports limiting the allowed access types through an optional second
generic parameter A
that can be one of ReadWrite
, ReadOnly
, or WriteOnly
. It defaults
to ReadWrite
, which allows all operations.
The size of this struct is the same as the size of the contained reference.
Implementations§
Source§impl<'a, T> VolatilePtr<'a, T>where
T: ?Sized,
Constructor functions.
impl<'a, T> VolatilePtr<'a, T>where
T: ?Sized,
Constructor functions.
These functions construct new VolatilePtr
values. While the new
function creates a VolatilePtr
instance with unrestricted access, there
are also functions for creating read-only or write-only instances.
Sourcepub unsafe fn new(pointer: NonNull<T>) -> VolatilePtr<'a, T, ReadWrite>
pub unsafe fn new(pointer: NonNull<T>) -> VolatilePtr<'a, T, ReadWrite>
Turns the given pointer into a VolatilePtr
.
§Safety
- The given pointer must be valid.
- No other thread must have access to the given pointer. This must remain true
for the whole lifetime of the
VolatilePtr
.
Sourcepub const unsafe fn new_read_only(
pointer: NonNull<T>,
) -> VolatilePtr<'a, T, ReadOnly>
pub const unsafe fn new_read_only( pointer: NonNull<T>, ) -> VolatilePtr<'a, T, ReadOnly>
Sourcepub const unsafe fn new_restricted<A>(
access: A,
pointer: NonNull<T>,
) -> VolatilePtr<'a, T, A>where
A: Access,
pub const unsafe fn new_restricted<A>(
access: A,
pointer: NonNull<T>,
) -> VolatilePtr<'a, T, A>where
A: Access,
Source§impl<'a, T, A> VolatilePtr<'a, T, A>where
T: ?Sized,
impl<'a, T, A> VolatilePtr<'a, T, A>where
T: ?Sized,
Sourcepub fn read(self) -> T
pub fn read(self) -> T
Performs a volatile read of the contained value.
Returns a copy of the read value. Volatile reads are guaranteed not to be optimized
away by the compiler, but by themselves do not have atomic ordering
guarantees. To also get atomicity, consider looking at the Atomic
wrapper types of
the standard/core
library.
§Examples
use volatile::{VolatilePtr, access};
use core::ptr::NonNull;
let value = 42;
let pointer = unsafe {
VolatilePtr::new_restricted(access::ReadOnly, NonNull::from(&value))
};
assert_eq!(pointer.read(), 42);
Sourcepub fn write(self, value: T)
pub fn write(self, value: T)
Performs a volatile write, setting the contained value to the given value
.
Volatile writes are guaranteed to not be optimized away by the compiler, but by
themselves do not have atomic ordering guarantees. To also get atomicity, consider
looking at the Atomic
wrapper types of the standard/core
library.
§Example
use volatile::VolatilePtr;
let mut value = 42;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
volatile.write(50);
assert_eq!(volatile.read(), 50);
Sourcepub fn update<F>(self, f: F)
pub fn update<F>(self, f: F)
Updates the contained value using the given closure and volatile instructions.
Performs a volatile read of the contained value, passes it to the
function f
, and then performs a volatile write of the returned value back to
the target.
use volatile::VolatilePtr;
let mut value = 42;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
volatile.update(|val| val + 1);
assert_eq!(volatile.read(), 43);
Sourcepub fn as_raw_ptr(self) -> NonNull<T>
pub fn as_raw_ptr(self) -> NonNull<T>
Extracts the wrapped raw pointer.
§Example
use volatile::VolatilePtr;
let mut value = 42;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
volatile.write(50);
let unwrapped: *mut i32 = volatile.as_raw_ptr().as_ptr();
assert_eq!(unsafe { *unwrapped }, 50); // non volatile access, be careful!
Sourcepub unsafe fn map<F, U>(self, f: F) -> VolatilePtr<'a, U, A>
pub unsafe fn map<F, U>(self, f: F) -> VolatilePtr<'a, U, A>
Constructs a new VolatilePtr
by mapping the wrapped pointer.
This method is useful for accessing only a part of a volatile value, e.g. a subslice or
a struct field. For struct field access, there is also the safe
map_field
macro that wraps this function.
§Examples
Accessing a struct field:
use volatile::VolatilePtr;
use core::ptr::NonNull;
struct Example { field_1: u32, field_2: u8, }
let mut value = Example { field_1: 15, field_2: 255 };
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
// construct a volatile pointer to a field
let field_2 = unsafe { volatile.map(|ptr| NonNull::new(core::ptr::addr_of_mut!((*ptr.as_ptr()).field_2)).unwrap()) };
assert_eq!(field_2.read(), 255);
Don’t misuse this method to do a non-volatile read of the referenced value:
use volatile::VolatilePtr;
let mut value = 5;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
// DON'T DO THIS:
let mut readout = 0;
unsafe {
let _ = volatile.map(|value| {
readout = *value.as_ptr(); // non-volatile read, might lead to bugs
value
});
};
§Safety
The pointer returned by f
must satisfy the requirements of Self::new
.
Source§impl<'a, T, A> VolatilePtr<'a, T, A>where
T: ?Sized,
Methods for restricting access.
impl<'a, T, A> VolatilePtr<'a, T, A>where
T: ?Sized,
Methods for restricting access.
Sourcepub fn restrict<To>(self) -> VolatilePtr<'a, T, A::Restricted>where
A: RestrictAccess<To>,
pub fn restrict<To>(self) -> VolatilePtr<'a, T, A::Restricted>where
A: RestrictAccess<To>,
Restricts access permissions to A
.
§Example
use volatile::access::{ReadOnly, WriteOnly};
use volatile::VolatilePtr;
let mut value: i16 = -4;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
let read_only = volatile.restrict::<ReadOnly>();
assert_eq!(read_only.read(), -4);
// read_only.write(10); // compile-time error
let no_access = read_only.restrict::<WriteOnly>();
// no_access.read(); // compile-time error
// no_access.write(10); // compile-time error
Source§impl<'a, T> VolatilePtr<'a, T, ReadWrite>where
T: ?Sized,
Methods for restricting access.
impl<'a, T> VolatilePtr<'a, T, ReadWrite>where
T: ?Sized,
Methods for restricting access.
Sourcepub fn read_only(self) -> VolatilePtr<'a, T, ReadOnly>
pub fn read_only(self) -> VolatilePtr<'a, T, ReadOnly>
Restricts access permissions to read-only.
§Example
use volatile::VolatilePtr;
let mut value: i16 = -4;
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
let read_only = volatile.read_only();
assert_eq!(read_only.read(), -4);
// read_only.write(10); // compile-time error
Sourcepub fn write_only(self) -> VolatilePtr<'a, T, WriteOnly>
pub fn write_only(self) -> VolatilePtr<'a, T, WriteOnly>
Restricts access permissions to write-only.
§Example
Creating a write-only pointer to a struct field:
use volatile::{VolatilePtr, map_field};
struct Example { field_1: u32, field_2: u8, }
let mut value = Example { field_1: 15, field_2: 255 };
let volatile = unsafe { VolatilePtr::new((&mut value).into()) };
// construct a volatile write-only pointer to `field_2`
let field_2 = map_field!(volatile.field_2).write_only();
field_2.write(14);
// field_2.read(); // compile-time error