【问题标题】:How to create a handle for application context in Rust?如何在 Rust 中为应用程序上下文创建句柄?
【发布时间】:2016-12-08 00:29:14
【问题描述】:

这是一个更高级别的问题,但是我不确定应该使用 Rust 的哪些功能来优化问题。

在编写具有工具 API 的图形应用程序的第一步时,我们可能希望传入一个context 参数,它公开应用程序的各个部分:

// Where the data lives.
struct Application {
    preferences: Preferences,
    windows: Vec<Windows>,
    documents: Vec<Document>,
}

// A view on the data to pass to tool-code.
struct AppContext {
    preferences: &Preferences,  // immutable
    window: &Window,            // immutable
    doc: &Document,             // mutable
    // ... real world use case has more vars ...
}

// example use
fn some_tool_uppercase(context: &mut AppContext, options: &ToolOptions) {
    // random example
    for w in context.document.words {
        w.to_uppercase();
    }
    context.window.redraw_tag();
}

在写这篇文章时,我遇到了借用检查器的问题,因为该文档还存储在其他文档的列表中 - 导致它同时在两个地方是可变的。

只是为了编译我的程序,目前我正在从列表中删除文档,运行该工具,然后在工具完成后将其添加回文档列表中。

虽然在某些情况下可以传递多个参数,但上面的示例被简化了。将上下文的每个成员都作为参数传递是不切实际的。

应如何将应用程序的上下文包装成可以传递到工具代码中的类型,而不会给借用检查器带来麻烦?

【问题讨论】:

    标签: rust borrow-checker


    【解决方案1】:

    &amp; 用于向函数临时借用数据。通常,当您需要对代码中多个位置的数据进行访问时,您将需要RcArc 类型。

    此外,您可能希望数据具有内部可变性。在这种情况下,您还需要将其包装在 CellRefCell 中。

    如果您的数据在线程之间共享,您还需要用MutexRwLock 包装它。

    现在,根据您的用例,您需要在数据结构中组合所有这些。更多信息请阅读:rust wrapper type composition

    您的示例可能如下所示:

    // Where the data lives.
    struct Application {
        preferences: Rc<Preferences>,
        windows: Rc<Vec<Windows>>,
        document: Rc<RefCell<Vec<Document>>>,
    }
    
    // A view on the data to pass to tool-code.
    struct AppContext {
        preferences: Rc<Preferences>,  // immutable
        window: Rc<Window>,            // immutable
        document: Rc<RefCell<Document>>,             // mutable
        // ... real world use case has more vars ...
    }
    
    // example use
    fn some_tool_uppercase(context: &mut AppContext, options: &ToolOptions) {
        // random example
        for w in (*context.document.borrow_mut()).words {
            w.to_uppercase();
        }
        context.window.redraw_tag();
    }
    

    或者如果它是多线程的:

    struct Application {
        preferences: Arc<RwLock<Preferences>>,
        windows: Arc<Mutex<Vec<Windows>>>,
        document: Arc<Mutex<Vec<Document>>,
    }
    ....
    

    【讨论】:

    • RefCell 真的需要在Arc&lt;Mutex&lt;RefCell&lt;...&gt;&gt;&gt; 中吗? Mutex::unlock 返回的守卫已经提供了对底层数据的可变访问权限。
    • 我认为你是对的。 RefCell 仅需要与 Rc 结合使用。 Rc&lt;RefCell&lt;...&gt;&gt;
    猜你喜欢
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-07
    • 1970-01-01
    • 2020-08-18
    • 2021-02-14
    • 1970-01-01
    相关资源
    最近更新 更多