首页 > 解决方案 > 当 lib 用户可能失败时如何使异步 rust lib 安全(参考)取决于调用和回调的单元借用检查

问题描述

我需要知道如何以 Rust 的方式解决这个问题,因为我的程序很恐慌。

我的库有一个用于检查事件和运行闭包的循环。目前我正在与简单的关闭事件作斗争。我的引擎有一个用于注册关闭事件和关闭窗口的 API。

// lib user code
// registering a callback which closes the window, when s.o. click the 'X'
let window_id = window.window_id;
engine.window_on_close(window.window_id, Box::new(|env| {
    env.engine.window_close(window_id);
}));

// lib code
// polling events (the glfw way)
for window in self.windows.borrow_mut().values_mut() {
    for (_, event) in glfw::flush_messages(&window.events) {
        match event {
            glfw::WindowEvent::Close => {
                window.invoke_on_close(&ce)?;
            },
            _ => {}
        }
    }
}

// struct Engine
pub fn window_on_close(&mut self, func: F)
    // where F: ...
{
    // ...
}

pub fn window_close(&mut self, window_id: glfw::WindowId) {
    let mut windows = self.windows.borrow_mut(); // panicked at 'already borrowed: BorrowMutError'
    let mut window = windows.remove(&window_id).expect("fix me");
    window.close();
}

当我点击“X”时,它很恐慌。

另一件事是,这是一个库,所以我不知道库用户是在关闭事件时关闭窗口(这是恐慌)还是用户只打印“你好,关闭”这会起作用,我认为这很糟糕lib 的设计问题,如果 lib 用户因为任何 RefCell 借用检查失败而陷入恐慌。

为了更清楚,我以线性方式写下代码。当然,现在您和我可以看到borrow_mut()直接编写此代码时可以避免的两次问题是什么,但是我的 lib 仅从用户空间运行代码以用于关闭事件,并且由于 lib 用户想要关闭窗口,因此失败了。无论如何,现在人们可以看到,代码有一个错误,因为它在迭代时改变了一个没有迭代器的哈希映射:

// 1. lib user registers close event:
let window_id = window.window_id;
engine.window_on_close(window.window_id, Box::new(|env| {
    env.engine.window_close(window_id);
}));

// 2. lib code polling events (the glfw way)
for window in self.windows.borrow_mut().values_mut() { // HERE: borrow_mut()
    for (_, event) in glfw::flush_messages(&window.events) {
        match event {
            glfw::WindowEvent::Close => {
                // pasted code from the callback: `engine.window_close(...)`
                let mut windows = self.window.borrow_mut(); // HERE: borrow_mut()
                let mut window = windows.remove(&window_id).expect("fix me");
                window.close();
            },
            _ => {}
        }
    }
}

我是对的吗,实际上我唯一需要解决的是 lib 用户不应该能够运行任何窗口突变,因为 windows 已经被借用了。别的什么都好。

您对此有何建议?

标签: asynchronousrust

解决方案


推荐阅读