的autoimplementation我有一個包含不安全的代碼用下面的方法一個結構:如何防止同步
use std::sync::Arc;
use std::thread;
#[derive(Debug)]
struct Foo<T> {
items: Vec<Box<(T, String)>>,
}
impl<T> Foo<T> {
pub fn add_element(&self, element: T, key: String) {
if !(self.items.iter().any(|i| i.1 == key)) {
let mut items = unsafe {change_mut(&(self.items))};
items.push(Box::new((element,key)));
}
}
}
unsafe fn change_mut<T>(x: &T) -> &mut T { // changes &self to &mut self
&mut *(x as *const T as *mut T)
}
fn main() {
let foo = Arc::new(Foo { items: vec!() });
let clone = foo.clone();
// This should not be possible, as it might lead to UB
thread::spawn(move || clone.add_element(1, String::from("one")));
println!("{:?}", *foo);
}
這個結構是完全安全的,直到有人開始使用這種方法,而多線程。但是,由於結構只包含Vec<Box<T,String>>
,所以Sync
默認實現,我想要阻止它。
我發現兩種方法可以做到這一點,這兩者都不是很大......
添加不執行
Sync
例如*const u8
一個結構領域,這顯然是相當糟糕的,因爲它最終導致不必要和不明確的代碼,並沒有清楚地表明我的意圖。impl !Sync for Struct {}
目前無法在馬鞍上銷售,根據this issue將被刪除。 相應的錯誤告訴我使用標記類型,但the documention也沒有提供解決我的問題的方法。
error: negative trait bounds are not yet fully implemented; use marker types for
now (see issue #13231)
--> src\holder.rs:44:1
|
44 | impl !Sync for Struct {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
請嘗試提供[MCVE],最好是連接到操場。當不需要猜測什麼被省略時,測試解決方案的正確性就容易得多。 –
(MCVE示例:https://play.rust-lang.org/?gist=bcfd5e96cfcd390de67bc738bd821108&version=stable) –
不,即使使用單個線程,代碼也不完全安全。 UB將&T投射到&mut T.你應該爲此使用UnsafeCell,這也應該解決你的同步問題。 – BurntSushi5