capypad
0 day streak
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
rust
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.