Struct VolatilePtr

Source
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.

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.

Source

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.
Source

pub const unsafe fn new_read_only( pointer: NonNull<T>, ) -> VolatilePtr<'a, T, ReadOnly>

Creates a new read-only volatile pointer from the given raw pointer.

§Safety

The requirements for Self::new apply to this function too.

Source

pub const unsafe fn new_restricted<A>( access: A, pointer: NonNull<T>, ) -> VolatilePtr<'a, T, A>
where A: Access,

Creates a new volatile pointer with restricted access from the given raw pointer.

§Safety

The requirements for Self::new apply to this function too.

Source§

impl<'a, T, A> VolatilePtr<'a, T, A>
where T: ?Sized,

Source

pub fn read(self) -> T
where T: Copy, A: Readable,

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);
Source

pub fn write(self, value: T)
where T: Copy, A: Writable,

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);
Source

pub fn update<F>(self, f: F)
where T: Copy, A: Readable + Writable, F: FnOnce(T) -> T,

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);
Source

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!
Source

pub unsafe fn map<F, U>(self, f: F) -> VolatilePtr<'a, U, A>
where F: FnOnce(NonNull<T>) -> NonNull<U>, A: Access, U: ?Sized,

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.

Source

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.

Source

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
Source

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

Trait Implementations§

Source§

impl<T, A> Clone for VolatilePtr<'_, T, A>
where T: ?Sized,

Source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T, A> Debug for VolatilePtr<'_, T, A>
where T: ?Sized,

Source§

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

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

impl<T, A> Hash for VolatilePtr<'_, T, A>
where T: ?Sized,

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<T, A> Ord for VolatilePtr<'_, T, A>
where T: ?Sized,

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl<T, A> PartialEq for VolatilePtr<'_, T, A>
where T: ?Sized,

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T, A> PartialOrd for VolatilePtr<'_, T, A>
where T: ?Sized,

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl<T, A> Pointer for VolatilePtr<'_, T, A>
where T: ?Sized,

Source§

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

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

impl<'a, T, A> Copy for VolatilePtr<'a, T, A>
where T: ?Sized,

Source§

impl<T, A> Eq for VolatilePtr<'_, T, A>
where T: ?Sized,

Auto Trait Implementations§

§

impl<'a, T, A> Freeze for VolatilePtr<'a, T, A>
where T: ?Sized,

§

impl<'a, T, A> RefUnwindSafe for VolatilePtr<'a, T, A>

§

impl<'a, T, A = ReadWrite> !Send for VolatilePtr<'a, T, A>

§

impl<'a, T, A = ReadWrite> !Sync for VolatilePtr<'a, T, A>

§

impl<'a, T, A> Unpin for VolatilePtr<'a, T, A>
where A: Unpin, T: ?Sized,

§

impl<'a, T, A> UnwindSafe for VolatilePtr<'a, T, A>
where T: RefUnwindSafe + ?Sized, A: UnwindSafe,

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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.