将带有引用的迭代器移动到线程中

Move an iterator with a reference into a thread

我有一个代表文件的类型。为简单起见,假设该类型包含一个包含文件内容的缓冲区。

还有一种构建迭代器的方法,它保存对内部缓冲区的引用。

文件类型是在主线程上创建的,但我需要将迭代器“发送”到线程中。

让我展示一下我正在尝试做什么

struct FileType {...}

let mut my_file_type = FileType::new("some_filename");
let mut my_iterator = my_file_type.iter();

external_library_object.start_process(move|_| {
    for _ in (0..10) {
        println!(my_iterator.next().unwrap());
    }
}

external_library_object(顺便说一句,它是 cpal 的设备)是……我无法更改的库中的对象。闭包参数虽然实现了 Send 特性。

这行不通,因为 my_file_type 活的时间不够长。 所以我尝试了 Mutex(所以迭代器是可变的)和 Arc(所以我们在两个线程之间共享迭代器)的组合

...

let mut my_file_type = FileType::new("some_filename");
let mut my_iterator = Arc::new(Mutex::new(my_file_type.iter()));

external_library_object.start_process(move|_| {
    let mut cloned = my_iterator.clone();
    for _ in (0..10) {
        println!(cloned.lock().unwrap().next().unwrap());
    }
}

但同样,这不起作用。我收到类似这样的错误:

xx |     let mut my_iterator = Arc::new(Mutex::new(my_file_type.iter()));
   |                                               ^^^^^^^^^^^^-------
   |                                                   |
   |                                                   borrowed value does not live long enough
   |                                                   argument requires that `my_file_type` is borrowed for `'static`
...
xx | }
   | - `my_file_type` dropped here while still borrowed

我有点卡在这里了。有没有办法在不同线程中使用引用其他对象(在本例中为缓冲区)的迭代器?

编辑:在我的特定情况下,迭代器是无限的并且闭包执行了多次。这就是我无法在线程内移动整个 FileType 的原因。

这很棘手,因为进程借用了一个迭代器,而迭代器又借用了一个结构。仅将迭代器放入 Arc<Mutex<>> 中是不够的,因为该指针可能仍然比它借用的 FileType 更有效。但是,我们不能将 FileType 和迭代器都放入引用计数结构中,因为该结构将是自引用的。

我能想到的最简单的解决方案(除了使用 scoped threads) is to create an iterator that owns the FileType, and then put it into a Arc<Mutex<>> (minimal playground example):

let my_file_type = FileType::new("test!");
let my_iterator = Arc::new(Mutex::new(my_file_type.into_iter()));

external_library_object.start_process(move |_| {
    for _ in 0..10 {
        println!("{:?}", my_iterator.lock().unwrap().next().unwrap());
    }
});

您只需要为您的 FileType 结构实现一个拥有的迭代器,如果它还不存在的话。