我寫了一些代碼。它的工作原理...但它是安全的嗎?鑄造任意類型的安全使用
use std::mem;
use std::ptr;
use std::marker::PhantomData;
struct Atomic<T: Copy>(AtomicUsize, PhantomData<T>);
impl<T: Copy> Atomic<T> {
unsafe fn encode(src: T) -> usize {
assert!(mem::size_of::<T>() <= mem::size_of::<usize>());
let mut dst = 0;
ptr::write(&mut dst as *mut usize as *mut T, src);
dst
}
unsafe fn decode(src: usize) -> T {
assert!(mem::size_of::<T>() <= mem::size_of::<usize>());
ptr::read(&src as *const usize as *const T)
}
fn new(val: T) -> Atomic<T> {
unsafe {
Atomic(AtomicUsize::new(Self::encode(val)), PhantomData)
}
}
fn load(&self, order: Ordering) -> T {
unsafe { Self::decode(self.0.load(order)) }
}
fn store(&self, val: T, order: Ordering) {
unsafe { self.0.store(Self::encode(val), order) }
}
}
impl<T: Copy + Default> Default for Atomic<T> {
fn default() -> Atomic<T> {
Self::new(T::default())
}
}
正如你所看到的,我寫一個任意Copy
值足夠小的尺寸爲usize
,並在Atomic
左右出貨。然後我讀出它作爲一個新的價值。
實質上,我使用usize
作爲大小爲size_of::<usize>()
的內存塊。
如果這是安全的,那麼下一步就是考慮更好的操作。
unsafe trait PackedInt {}
unsafe impl PackedInt for u8 {}
unsafe impl PackedInt for i8 {}
unsafe impl PackedInt for u32 {}
unsafe impl PackedInt for i32 {}
unsafe impl PackedInt for u64 {}
unsafe impl PackedInt for i64 {}
impl<T: Copy + PackedInt> Atomic<T> {
fn compare_and_swap(&self, current: T, new: T, order: Ordering) -> T {
unsafe {
Self::decode(self.0.compare_and_swap(
Self::encode(current),
Self::encode(new),
order
))
}
}
fn fetch_add(&self, val: T, order: Ordering) -> T {
unsafe {
Self::decode(self.0.fetch_add(Self::encode(val), order))
}
}
fn fetch_sub(&self, val: T, order: Ordering) -> T {
unsafe {
Self::decode(self.0.fetch_sub(Self::encode(val), order))
}
}
}
這些當然並不總是溢出特別懂事(因爲兩個「平等」的價值可能因T
之外位比較不等),但他們似乎仍然明確的...我認爲。
那麼,這是安全的,爲什麼?
你是指[安全的鏽定義](http://doc.rust-lang.org/reference.html#behavior-not-considered-unsafe)(也相關,[未定義的行爲](http ://doc.rust-lang.org/reference.html#behavior-considered-undefined))?或者你的意思是更普遍的「安全」類型? – Shepmaster
鏽的定義,主要是。但是,對特別令人驚訝但技術上安全的問題的評論將是一個不錯的補充。大端系統*上的 – Veedrac