It sounds to me raw pointers not being Send + Sync is weird. Here is why:
- It is safe to send or share them.
unsafe is to dereference them. And this is unsafe even when not shared between threads.
- One can circumvent that very easily with a few casts.
- Why is
AtomicPtr: Send + Sync then? One may store a pointer to a local variable on an AtomicPtr shared between threads and then another thread could load such pointer and dereference it and… Well, read item 1.
Explanation:
- Supposing they are
Send:
let var = 5;
let ptr = &var as *const i32;
let thread = thread::spawn(move || {
println!("{:?}", ptr);
}
There is no problem in such code. The problem comes if the program dereferences such pointer, which is unsafe.
- Working around this restriction:
let var = 5;
let ptr = &var as *const i32 as usize;
let thread = thread::spawn(move || {
println!("{:?}", ptr as *const i32);
}
- I see no difference in the between:
let var = 5;
let ptr = &var as *const i32;
let thread = thread::spawn(move || {
println!("{}", unsafe { *ptr });
}
And
let var = 5;
let mut ptr = AtomicPtr::new(&var as *const i32);
let thread = thread::spawn(move || {
println!("{}", unsafe { **ptr.get_mut() });
}