如何使用运算符“?” 与共享 mpsc?

wan*_*len 2 rust

我正在努力应用在“运算符可以在使用共享 mpsc 通道返回我的代码的函数中使用”一章中获得?Result 知识

这是最少的代码:

use std::sync::{ mpsc, Arc, Mutex };
use std::error::Error;

fn main() 
{
}

fn sh_rx_get( sh_rx : Arc< Mutex< mpsc::Receiver< usize > > > ) -> Result< usize, Box<dyn Error> >
{
  let rx = sh_rx.lock()?;
  let r = rx.try_recv()?;
  Ok( r )
}

Run Code Online (Sandbox Code Playgroud)

我得到的错误:

error[E0515]: cannot return value referencing function parameter `sh_rx`
  --> src/main.rs:10:12
   |
10 |   let rx = sh_rx.lock()?;
   |            -----^^^^^^^^
   |            |
   |            returns a value referencing data owned by the current function
   |            `sh_rx` is borrowed here
Run Code Online (Sandbox Code Playgroud)

网上游乐场

有什么建议或提示吗?

use*_*968 5

此错误的原因是std::sync::Mutex::lock()返回一个Result<MutexGuard<'_, T>, PoisonError<MutexGuard<'_, T>>>. 正如您所看到的,该错误情况Result带有借用原始锁的生命周期('_中的生命周期MutexGuard)。编译器试图告诉您,通过 返回错误?将返回借用值 -PoisonError<MutexGuard<'_, T>>>该值是在此函数中创建的,并且仅在此函数中有效;这将创建一个悬空引用,因此会出现编译错误。

有问题的本地借用(“当前函数拥有的数据”)是在sh_rx.lock()调用时隐式创建的。Rust 会自动引用Arc sh_rx,然后取消引用ArcMutex其中.lock()实际定义。

lock()即使在错误情况下也会返回借用锁的值的原因是,如果另一个线程在持有锁时发生恐慌,则锁定会失败;这可能意味着受锁保护的数据处于不一致的状态。PoisonError有一个into_inner()方法无论如何都会获取锁,并且需要借用原始锁来执行此操作。

您可以通过将 转换PoisonError为不借用锁的其他类型来解决此问题。例如:

let rx = sh_rx.lock().map_err(|e| e.to_string())?;
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为有一个From<String> for Box<dyn Error> in std, - 运算符自动使用?它来将 转换StringBox<dyn Error>函数返回的 。