P.MEM.SPT.01 使用 RefCell<T> 时宜使用 try_borrow/try_borrow_mut 方法

【描述】

Rust 的 RefCell<T> 在运行时会对通过 borrow/borrow_mut 方法借用出去的不可变借用和可变借用进行检查。如果发现违反了借用规则的情况,则会 Panic。

所以在一些多线程场景下,开发者可能对细粒度的操作加了锁同步,但是没有对 RefCell<T> 进行加锁,此时宜用 try_borrow/try_borrow_mut 来代替 borrow/borrow_mut,以避免在运行时因为违反借用检查规则而出现 Panic。

【反例】


#![allow(unused)]
fn main() {
// 不符合
// 以下两个函数会让 C 函数在多线程下调用
// 运行过程中有一定几率会出现 Panic
pub extern "C" fn nic_udrv_suspend() {
    NIC_ENTITY.borrow_mut().suspend(); // suspend()需要可变引用
}

pub extern "C" fn nic_udrv_buf_recycle(buf_id: usize) {
    NIC_ENTITY.borrow().buf_recycle(buf_id); // buf_recycle()内有锁可以避免多线程竞争
}
}

【正例】


#![allow(unused)]
fn main() {
// 符合
// 以下两个函数会让 C 函数在多线程下调用
// 使用 try_borrow 或 try_borrow_mut 可以避免运行过程中出现 Panic
pub extern "C" fn nic_udrv_suspend() {
    if let Ok(entity) = NIC_ENTITY.try_borrow_mut() {
        entity.suspend(); // suspend()需要可变引用
    }
}

pub extern "C" fn nic_udrv_buf_recycle(buf_id: usize) {
    if let Ok(entity) = NIC_ENTITY.try_borrow() {
        entity.buf_recycle(buf_id); // buf_recycle()内有锁可以避免多线程竞争
    }
}
}