我有这个Rust程序:
use std::{thread, time};
static mut c:bool = false;
fn main() {
unsafe {
// call some FFI program which sets up signals
c = false;
while !c {
thread::sleep(time::Duration::from_millis(10));
}
}
}
我将c
的指针指向某个FFI程序,该程序设置了更改c
的信号。我怎样才能确保编译器没有消除while
循环,因为它假定c
永远不会改变?
C有一个volatile
关键字,告诉编译器不要在这些示例中进行优化。我怎么能告诉Rust编译器呢?
(我尝试阅读LLVM IR代码,但无法弄清楚如何理解它。)
答案 0 :(得分:2)
不,静态变量不易变。
Rust中的正确解决方案是使用AtomicBool
。以下示例(来自std::sync::atomic
)与您要执行的操作非常相似:
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
fn main() {
let spinlock = Arc::new(AtomicUsize::new(1));
let spinlock_clone = spinlock.clone();
let thread = thread::spawn(move|| {
spinlock_clone.store(0, Ordering::SeqCst);
});
// Wait for the other thread to release the lock
while spinlock.load(Ordering::SeqCst) != 0 {}
if let Err(panic) = thread.join() {
println!("Thread had an error: {:?}", panic);
}
}
你可以通过从信号处理程序到Rust的回调来实现这一点。
还有不安全的函数std::ptr::read_volatile
和std::ptr::write_volatile
,它们可用于直接访问内存。通常,这些只应用于访问硬件寄存器或实现安全抽象。