在没有 Send/Sync 特征的结构上采用 AtomicPtr

Adopt AtomicPtr on structs without Send/Sync traits

最近我正在尝试通过 psutil crate 监控系统指标。 (我知道还有另一个库 heim 具有异步功能。)

我曾经使用 AtomicPtr 包装静态 Process 结构。编译器没有抱怨。但是很快我就遇到了 运行-time 错误,当我在 Process 对象上调用 API 时。

终于发现是AtomicPtr<Process>pid变了,导致报错,因为新pid的进程不存在。

然后我尝试了另一种方法。我实施了以下 ProcessWrapper,它有效。而 pid 并没有改变。

编辑:ProcessWrapper 是多余的,Process 本身与 Send/Sync

那么我的问题来了:

use psutil::process::Process;
use lazy_static::lazy_static;
use std::process;
use std::sync::{
    atomic::{AtomicPtr, AtomicU64, Ordering}, Mutex, Arc
};

lazy_static!{
    static ref PROCESS1 : AtomicPtr<Process> = AtomicPtr::new(&mut Process::new(process::id()).unwrap());
    static ref PROCESS2: Arc<Mutex<Process>> = Arc::new(Mutex::new(
        Process::new(std::process::id()).unwrap()
    ));

}


fn main() {
    let process1 = unsafe{PROCESS1.load(Ordering::SeqCst).as_ref()}.unwrap();
    //let process2 = &PROCESS2.lock().unwrap(); 
    println!("{}", process1.pid()); // Unexpected! It is different from the real `process::id`
    //println!("{}", process2.pid()); // It performs well, and it also makes the above one valid
    println!("{}", process::id());
}



// redundant, the `Process` is with `Send/Sync` trait
use process_wrapper::*;
mod process_wrapper{
    use psutil::process::{Process, ProcessResult,MemoryInfo};
    use psutil::Percent;

    #[derive(Debug)]
    pub struct ProcessWrapper{
        pub p: Process
    }
    
    unsafe impl Send for ProcessWrapper{}
    unsafe impl Sync for ProcessWrapper{}
}


AtomicPtr::new(&mut Process::new(process::id()).unwrap())

您在堆栈上创建 Process 对象,并将指向该 堆栈 对象的可变指针存储到 AtomicPtr 中。 PROCESS1 完成初始化后,将释放 Process 对象,并且您的 AtomicPtr 指向未初始化的内存。

psutil:process::Process 既是 Send 又是 SyncArc<Mutex<Process>> 可以正常工作,而且很安全。不确定为什么需要 AtomicPtr.