rust / expert
Snippet
Pinned Memory for Async State Machines
The 'Pin' wrapper ensures that a value stays at a fixed memory address. This is critical for self-referential structs where a field stores a pointer to another field within the same object. If the object moved, the internal pointer would become dangling.
snippet.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
use std::pin::Pin;use std::marker::PhantomPinned;struct SelfReferential {data: String,ptr: *const String,_pin: PhantomPinned,}impl SelfReferential {pub fn new(data: String) -> Pin<Box<Self>> {let res = SelfReferential {data,ptr: std::ptr::null(),_pin: PhantomPinned,};let mut boxed = Box::pin(res);let self_ptr: *const String = &boxed.data;unsafe {let mut_ref: Pin<&mut Self> = boxed.as_mut();Pin::get_unchecked_mut(mut_ref).ptr = self_ptr;}boxed}}
Breakdown
1
_pin: PhantomPinned,
A marker to inform the compiler that this type does not implement the Unpin trait.
2
let mut boxed = Box::pin(res);
Allocates the struct on the heap and pins it, preventing it from being moved.