【问题标题】:Pass data from a callback closure to mpsc producer in Rust将数据从回调闭包传递给 Rust 中的 mpsc 生产者
【发布时间】:2021-09-11 23:57:24
【问题描述】:

我有以下代码。我创建了一个 mpsc 通道,目标是将发送者传递给闭包,该闭包将注册为带有库的回调,然后将来自回调的数据发送到通道以供其他地方使用。

use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::thread;

fn init(sender: Sender<&[u8]>) {
    let handle_event = |x:i32, data:&[u8]| {
        sender.send(data).unwrap();
        };
    //handle will be registered as callback with some library
    //and used later in this thread
    sender.send("Callback registered".as_bytes()).unwrap();
}

fn main() {
    let (producer, bottle) = channel();
    let child = thread::spawn(move ||init(producer));
    for message in bottle {
        //process data
    }
    let res = child.join();
    
}

但我在编译时收到以下错误:

error[E0312]: lifetime of reference outlives lifetime of borrowed content...
 --> src/main.rs:7:21
  |
7 |         sender.send(data).unwrap();
  |                     ^^^^
  |
note: ...the reference is valid for the anonymous lifetime defined on the function body at 5:24...
 --> src/main.rs:5:24
  |
5 | fn init(sender: Sender<&[u8]>) {
  |                        ^^^^^
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the body at 6:24
 --> src/main.rs:6:24
  |
6 |       let handle_event = |x:i32, data:&[u8]| {
  |  ________________________^
7 | |         sender.send(data).unwrap();
8 | |         };
  | |_________^

我该如何解决这个问题?我注册回调的那一行也会抛出这个错误。

explicit lifetime required in the type of `sender`
   |
64 |         .sample_cb(handle_event)
   |          ^^^^^^^^^ lifetime `'static` required

回调应该是这个特征

pub trait SampleCb: FnMut(i32, &[u8]) + 'static {}

我不确定第二个错误是否是由于第一个错误引起的,因为第一个错误无论是否注册为回调都会发生,如here

【问题讨论】:

    标签: rust


    【解决方案1】:

    要修复您的第一个错误,只需在 Sender&lt;&amp;[u8]&gt; 上命名生命周期,然后将该生命周期添加到 handle_event 的参数中:

    // name the lifetime 'a
    fn init<'a>(sender: Sender<&'a [u8]>) {
        // take in &'a [u8] instead of &[u8]
        let handle_event = |x: i32, data: &'a [u8]| {
            sender.send(data).unwrap();
        };
        // ...
    }
    

    Playground link

    【讨论】:

    • 这是否意味着数据将在发送者的生命周期内保持活动状态?从逻辑上讲,它应该在接收者完成处理后立即丢弃。
    • @SamThomas 类型系统不知道接收者何时使用数据。接收方可以在消费之前等待任意时间,因此数据需要在发送方的生命周期内有效。
    • 明白了。既然发送者将永远存在,这是否意味着来自所有回调的所有“数据”都将永远存在?这会是内存爆炸吗?我必须手动将其放入接收器吗?
    • 如果你想释放内存,我建议使用接收者可以丢弃的自有数据类型,例如发送Vec&lt;[u8]&gt;s 而不是&amp;[u8]s。如果您有很多不想为其分配 Vec 的切片,您还可以考虑使用 Cow&lt;[u8]&gt;,它允许您同时发送切片和 Vecs。
    • 那么我对上述将数据生命周期与发送者关联的方法的内存爆炸是否正确?因为回调会被多次调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-03
    相关资源
    最近更新 更多