我正在试验Rust的Arc<Mutex>
,尝试将其用于默认示例中没有的结构,而是默认初始化的自定义结构:
use std::sync::{Arc, Mutex};
#[macro_use]
extern crate lazy_static; // lazy_static = "1.2.0"
pub struct FooBar {}
lazy_static! {
static ref FOO_BAR: Arc<Mutex<Option<FooBar>>> = Arc::new(Mutex::new(None));
}
pub fn unpack_foo_bar() {
let foo_bar_arc = Arc::clone(&FOO_BAR);
let foo_bar_mutex_result = foo_bar_arc.lock();
let foo_bar_mutex = foo_bar_mutex_result.unwrap();
let foo_bar = foo_bar_mutex.unwrap();
// do something
}
稍后,通过替换选项的内容来初始化静态FOO_BAR
变量。
上面的代码无法编译:
error[E0507]: cannot move out of borrowed content
--> src/lib.rs:15:19
|
15 | let foo_bar = foo_bar_mutex.unwrap();
| ^^^^^^^^^^^^^ cannot move out of borrowed content
如果将FooBar
替换为e。 G。 u32
。该代码也无法使用String
进行编译,但是该类型具有内置的克隆方法,而我的类型可能不一定具有。
使用foo_bar_mutex.as_ref().unwrap()
的短暂时间,我还有哪些其他选择,特别是如果我想将FooBar
实例的提取抽象为一种方法,例如:
pub fn unpack_foo_bar() -> Option<FooBar> {
let foo_bar_arc = Arc::clone(&FOO_BAR);
let foo_bar_mutex_result = foo_bar_arc.lock();
let foo_bar_mutex = foo_bar_mutex_result.unwrap();
let foo_bar_option = *foo_bar_mutex;
foo_bar_option
}
在这种情况下,编译器将引发几乎相同的错误,即
error[E0507]: cannot move out of borrowed content
--> src/main.rs:34:26
|
11 | let foo_bar_option = *foo_bar_mutex;
| ^^^^^^^^^^^^^^
| |
| cannot move out of borrowed content
| help: consider using a reference instead: `&*foo_bar_mutex`
我认为,如果容易克隆FooBar
,这会简单得多,但是在现实世界中,我将此示例基于FooBar
,该字段是a的实例没有派生Clone
特性的第三方库对象。
使用Option::take
将仅使包含的变量可用一次。我不是在尝试拥有FooBar
实例的所有权。只要我可以调用它的方法,我都不在乎是否拥有它。返回引用会很好,但是这样做时,编译器会抱怨:
pub fn unpack_foo_bar() -> &Option<FooBar> {
let foo_bar_arc = Arc::clone(&FOO_BAR);
let foo_bar_mutex_result = foo_bar_arc.lock();
let foo_bar_mutex = foo_bar_mutex_result.unwrap();
let foo_bar_option = foo_bar_mutex.as_ref();
foo_bar_option
}
编译器的响应:
error[E0106]: missing lifetime specifier
--> src/main.rs:30:28
|
7 | pub fn unpack_foo_bar() -> &Option<FooBar> {
| ^ help: consider giving it a 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
使用&*foo_bar_mutex
进行实验并在返回类型中添加'static
都会打开随后的编译器错误。
我还尝试在to_owned()
引用上试验FooBar
,偶然发现了owning_ref板条箱,但可惜的是,还没有弄清楚如何使返回的引用起作用。
鉴于似乎无法将对Option<FooBar>
的引用传递给外部函数调用者,我决定通过允许将依赖于FooBar
实例的方法作为a来传递,从而完全避免了这个问题。关闭:
pub fn unpack_foo_bar(use_foo_bar: fn(&FooBar)) {
let foo_bar_arc = Arc::clone(&FOO_BAR);
let foo_bar_mutex_result = foo_bar_arc.lock();
let foo_bar_mutex = foo_bar_mutex_result.unwrap();
let foo_bar_reference = foo_bar_mutex.as_ref().unwrap();
// pass in the closure that needs the foo bar instance
use_foo_bar(foo_bar_reference);
}