volatile/lib.rs
1//! Provides volatile wrapper types for raw pointers.
2//!
3//! The volatile wrapper types in this crate wrap a pointer to any [`Copy`]-able
4//! type and provide volatile memory access to wrapped value. Volatile memory accesses are
5//! never optimized away by the compiler, and are useful in many low-level systems programming
6//! and concurrent contexts.
7//!
8//! This crate provides two different wrapper types: [`VolatilePtr`] and [`VolatileRef`]. The
9//! difference between the two types is that the former behaves like a raw pointer, while the
10//! latter behaves like a Rust reference type. For example, `VolatilePtr` can be freely copied,
11//! but not sent across threads because this could introduce mutable aliasing. The `VolatileRef`
12//! type, on the other hand, requires exclusive access for mutation, so that sharing it across
13//! thread boundaries is safe.
14//!
15//! Both wrapper types *do not* enforce any atomicity guarantees; to also get atomicity, consider
16//! looking at the `Atomic` wrapper types found in `libcore` or `libstd`.
17//!
18//! ## Why is there no `VolatileCell`?
19//!
20//! Many people expressed interest in a `VolatileCell` type, i.e. a transparent wrapper type that
21//! owns the wrapped value. Such a type would be similar to [`core::cell::Cell`], with the
22//! difference that all methods are volatile.
23//!
24//! Unfortunately, it is not sound to implement such a `VolatileCell` type in Rust. The reason
25//! is that Rust and LLVM consider `&` and `&mut` references as _dereferencable_. This means that
26//! the compiler is allowed to freely access the referenced value without any restrictions. So
27//! no matter how a `VolatileCell` type is implemented, the compiler is allowed to perform
28//! non-volatile read operations of the contained value, which can lead to unexpected (or even
29//! undefined?) behavior. For more details, see the discussion
30//! [in our repository](https://github.com/rust-osdev/volatile/issues/31)
31//! and
32//! [in the `unsafe-code-guidelines` repository](https://github.com/rust-lang/unsafe-code-guidelines/issues/411).
33
34#![no_std]
35#![cfg_attr(feature = "unstable", feature(core_intrinsics))]
36#![cfg_attr(feature = "unstable", feature(slice_range))]
37#![cfg_attr(feature = "unstable", feature(slice_ptr_get))]
38#![cfg_attr(feature = "very_unstable", feature(const_trait_impl))]
39#![cfg_attr(feature = "very_unstable", feature(unboxed_closures))]
40#![cfg_attr(feature = "very_unstable", feature(fn_traits))]
41#![cfg_attr(feature = "very_unstable", feature(effects))]
42#![cfg_attr(docsrs, feature(doc_auto_cfg))]
43#![cfg_attr(feature = "unstable", allow(internal_features))]
44#![warn(missing_docs)]
45#![deny(unsafe_op_in_unsafe_fn)]
46#![doc(test(attr(deny(warnings))))]
47#![doc(test(attr(allow(dead_code))))]
48#![doc(test(attr(allow(unused_variables))))]
49
50#[cfg(feature = "derive")]
51pub use volatile_macro::VolatileFieldAccess;
52
53pub use volatile_ptr::VolatilePtr;
54pub use volatile_ref::VolatileRef;
55
56pub mod access;
57mod volatile_ptr;
58mod volatile_ref;