如何返回对静态Lat互斥锁内部自定义结构的Option的引用?

时间:2019-02-03 08:40:30

标签: rust clone mutex borrow-checker reference-counting

我正在试验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);
}

0 个答案:

没有答案