从 Mutex 中同时借用引用和保护

Borrowing reference and guard together from a Mutex

我正在尝试封装一些代码以避免重复它,涉及从 Mutex 中借用数据以及随后的进一步操作(我不在这个问题范围内,但这是激励因素)。

下面的示例代码抱怨 guard 活得不够长。但这正是我以专门为此目的设计的结构返回 guard 的原因。

这是借阅检查器的限制吗?关于解决此问题的任何建议?

use std::sync::{Mutex,MutexGuard};
use std::ops::DerefMut;

pub struct InnerData {
    count: i32  // sample only
}

pub struct Data {
    pub inner_data: Mutex<InnerData>
}

pub struct BorrowedInnerData<'a> {
    pub inner_data: &'a mut InnerData,
    guard: MutexGuard<'a,InnerData>,
}

impl Data {
    pub fn borrow_inner_data<'a>(&'a mut self) -> BorrowedInnerData<'a> {
        let guard = self.inner_data.lock().unwrap();
        BorrowedInnerData {
            inner_data: guard.deref_mut(),
            guard: guard,
        }
    }
}

fn main() {
    let mut data = Data {
        inner_data: Mutex::new( InnerData {
            count: 5
        }),
    };

    let borrowed_inner_data = data.borrow_inner_data();
}

我们来看看DerefMut trait:

pub trait DerefMut: Deref {
    fn deref_mut(&'a mut self) -> &'a mut Self::Target;
}

这意味着当调用 deref_mut 时,将返回一个引用,该引用 与被取消引用的值 一样长。但是,当您将其移动到 BorrowedInnerData 时,您正在移动 guard。这意味着该值停止存在于一个内存位置并从一个新位置开始。作为 ,移动守卫完全有可能使引用无效。这会很糟糕并导致崩溃(在最好的情况下)。

但是,没有真正的理由保留 guardinner_data。由于 DerefDerefMutMutexGuard<InnerData> 可以像 &InnerData&mut InnerData 一样使用。只需从结构中删除 inner_data 并保留 guard.