如何在Rust中为应用程序上下文创建句柄?

时间:2016-12-08 00:29:14

标签: rust borrow-checker

这是一个更高级别的问题,但是我不确定应该使用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();
}

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

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

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

如何将应用程序的上下文包装到可以传递到工具代码中的类型中,而不会导致借用检查器的复杂化?

1 个答案:

答案 0 :(得分:0)

&用于临时向函数借用数据。通常,当您需要访问代码中多个位置的数据时,您需要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>>,
}
....