So does Rust, in unsafe blocks. Is there anything that can be done in C that can’t be done in unsafe Rust?
So does Rust, in unsafe blocks. Is there anything that can be done in C that can’t be done in unsafe Rust?
Google even sponsored the work to clean the Linux kernel from them.
Duff's device <https://en.wikipedia.org/wiki/Duff's_device>.
I don't think they are.
> You can write Rust code with the same observable behavior as Duff's device in C.
Yes, turing complete languages can do that.
Why anyone would want that on purpose, I don't know.
In this particular case it's the `Sync` trait and the generell rules around sharing data.
I was specifically referring to the things you can do in `unsafe` blocks.
This program prints "12". The only difficulty is that Rust's designers have intentionally made this pattern difficult by marking raw pointers as !Send, but you can get around that by wrapping them in a Send type.
use std::{time::Duration, ops::{DerefMut, Deref}};
struct SendWrapper<T>(*mut T);
impl<T> Deref for SendWrapper<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.0.as_ref() }.unwrap()
}
}
impl<T> DerefMut for SendWrapper<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.0.as_mut() }.unwrap()
}
}
unsafe impl<T> Send for SendWrapper<T> {}
fn main() {
let mut x = 10;
let p1: *mut usize = &mut x;
let p2: *mut usize = &mut x;
let mut s1 = SendWrapper(p1);
let mut s2 = SendWrapper(p2);
let j1 = std::thread::spawn(move || {
*s1.deref_mut() += 1;
});
let j2 = std::thread::spawn(move || {
std::thread::sleep(Duration::from_secs(1));
*s2.deref_mut() += 1;
});
j1.join().unwrap();
j2.join().unwrap();
println!("x: {}", x);
}