Skip to main content

catalejo_memory/
behavior.rs

1//! Behavior and guarantees provided by types to be in and out of memory.
2
3use core::mem::MaybeUninit;
4
5/// A marker trait that describes an "immortal" type.
6///
7/// By "immortal", this denotes a type that is fixed in size and has no lifetime dependencies.
8pub trait Immortal: Sized + 'static {}
9
10/// Blanket implementation for all "immortal" types.
11impl<I> Immortal for I where I: Sized + 'static {}
12
13/// A trait that models an unassociated (i.e., no attached lifetime, immortal), trivially-copiable type that can be read from memory.
14///
15/// # Hardware Coherence Model
16///
17/// When dealing with concurrent, un-synchronized memory reads, understanding the physical hardware access model is critical:
18///
19/// * **Machine-Word Coherence:** The hardware guarantee that a CPU can fetch data up to its native word size (e.g., 64-bits on x86_64) in a single, indivisible memory bus transaction.
20/// * **Snapshot Coherence:** A read resulting from a single, indivisible transaction. The resulting value represents the exact state of the memory at an isolated point in time.
21/// * **Mixed Coherence (Tearing):** A read assembled from multiple hardware transactions. If another thread mutates the memory between these fetches, the resulting value is a temporal mix of old and new bytes.
22///
23/// Mixed coherence inevitably occurs under two conditions:
24/// 1. The data type exceeds the hardware machine word (e.g., attempting a concurrent read on a 256-byte `struct`).
25/// 2. The memory access is **unaligned**. For example, reading an 8-byte `u64` that physically straddles two distinct CPU cachelines forces the hardware to split the read into two distinct fetches, immediately destroying snapshot coherence.
26///
27/// # Safety
28///
29/// To be able to implement this trait safely, all the following requirements must have been satisfied:
30///
31/// * The type is valid and presents no broken safety-related invariants in all possible bit-permutations, as well as be able to survive a round-trip through both bitstream and whole-type states.
32/// * The type must be appropriate for snapshot and mixed-coherence reads. Particularly, for a single-component type, it must be safe to read and write from a
33///   concurrently mutated memory region where tearing is inherently permitted, without resulting in type-level undefined behavior. For a multi-component type, it may present inter-component tearing, but the individual components still correspond to a valid observed value.
34/// * The type is safe to transmute back-and-forth to a byte-level representation.
35///
36/// As a general rule, do not implement this for types or any primitive that possesses an illegal bit-pattern (e.g., `bool`, or an enum with a non-explicit **repr** with non-exhaustive discriminants).
37///
38/// # Data Validity
39///
40/// As a global concern, validate that:
41///
42/// - The alignment for the type you're reading is correct.
43/// - The type itself or individual primitive components do not cross cacheline boundaries.
44///
45/// If these concerns are not satified, the data remains safe to read, but may prove of little use due to low validity.
46pub unsafe trait Unassociated: Immortal + Copy {}
47
48// SAFETY: If `T` implements `Unassociated`, `MaybeUninit` does too.
49unsafe impl<T> Unassociated for MaybeUninit<T> where T: Unassociated {}
50
51// SAFETY: Unsigned 8-bit integers possess no safety-related invariants and are valid for all possible bit-permutations.
52unsafe impl Unassociated for u8 {}
53
54// SAFETY: Signed 8-bit integers possess no safety-related invariants and are valid for all possible bit-permutations.
55unsafe impl Unassociated for i8 {}
56
57// SAFETY: Unsigned 16-bit integers possess no safety-related invariants and are valid for all possible bit-permutations.
58unsafe impl Unassociated for u16 {}
59
60// SAFETY: Signed 16-bit integers possess no safety-related invariants and are valid for all possible bit-permutations.
61unsafe impl Unassociated for i16 {}
62
63// SAFETY: Unsigned 32-bit integers possess no safety-related invariants and are valid for all possible bit-permutations.
64unsafe impl Unassociated for u32 {}
65
66// SAFETY: Signed 32-bit integers possess no safety-related invariants and are valid for all possible bit-permutations.
67unsafe impl Unassociated for i32 {}
68
69// SAFETY: Unsigned 64-bit integers possess no safety-related invariants and are valid for all possible bit-permutations.
70unsafe impl Unassociated for u64 {}
71
72// SAFETY: Signed 64-bit integers possess no safety-related invariants and are valid for all possible bit-permutations.
73unsafe impl Unassociated for i64 {}
74
75// SAFETY: Pointer-sized unsigned integers possess no safety-related invariants and are valid for all possible bit-permutations.
76unsafe impl Unassociated for usize {}
77
78// SAFETY: Pointer-sized signed integers possess no safety-related invariants and are valid for all possible bit-permutations.
79unsafe impl Unassociated for isize {}
80
81// SAFETY: 32-bit floats possess no safety-related invariants. NaN bit patterns are mathematically valid states.
82unsafe impl Unassociated for f32 {}
83
84// SAFETY: 64-bit floats possess no safety-related invariants. NaN bit patterns are mathematically valid states.
85unsafe impl Unassociated for f64 {}
86
87// SAFETY: The element type `U` implements `Unassociated`, therefore, a const-generic array does too.
88unsafe impl<U, const N: usize> Unassociated for [U; N] where U: Unassociated {}
89
90// SAFETY: A thin raw pointer has no illegal bit patterns, as every bit pattern is a valid
91// pointer value, it is byte-transmutable, and a torn read still yields a valid (if mangled and
92// meaningless) address that is never dereferenced. The `P: Immortal` bound supplies
93// `Sized` (the pointer is thin, a single machine word) and `'static` (satisfying the
94// `Immortal` supertrait of `Unassociated`).
95// NOTE(warning): This is to be used as an escape hatch to model pointers in a foreign address space.
96unsafe impl<P> Unassociated for *const P where P: Immortal {}
97
98// SAFETY: A thin raw pointer has no illegal bit patterns, as every bit pattern is a valid
99// pointer value, it is byte-transmutable, and a torn read still yields a valid (if mangled and
100// meaningless) address that is never dereferenced. The `P: Immortal` bound supplies
101// `Sized` (the pointer is thin, a single machine word) and `'static` (satisfying the
102// `Immortal` supertrait of `Unassociated`).
103// NOTE(warning): This is to be used as an escape hatch to model pointers in a foreign address space.
104unsafe impl<P> Unassociated for *mut P where P: Immortal {}