rust 我如何将一个impl Fn Trait对象传递到多个线程中,就像使用线程池一样

js81xvg6  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(171)

(Rust编译器1.64.0版)我尝试做的是:我希望有一个类似于minecraftesque世界的世界生成过程。因此,我希望能够传递一个函数给一些世界生成器,并在每个块上执行这个函数。到目前为止,这个过程是单线程的,我希望至少块生成过程是多线程的,因为这不需要同步,这是一个非常多处理器友好的事情。
现在,我有一个函数generate_world(self: &mut Self, generator : impl Fn(isize, isize, isize) ->BlockType) ->(){}
这个函数在中间有一个大的for循环,每当需要时,它就单线程地调用函数生成器。
我现在决定使用线程池crate,这允许我创建一个pool: ThreadPool,并调用pool.execute(move ||{});来执行一个作业(比如,首先做一些准备,然后生成一个块,或者更确切地说,一次生成一个完整的流)。
我还遇到的是,在第一次调用时,生成器被移到线程函数中,但这(显然)已经通过装箱和弧化它来修复。
现在,我当然已经尝试将生成器函数放在那里,并且正确地警告我应该在生成器函数上指定+ Send和+ Sync,我毫不犹豫地这样做了。问题是现在我还应该指定一个生存期,建议是:'static。不幸的是,我的程序结构不允许我这样做,因为函数中的一些组件的生存期确实受到主函数的一部分的限制。
我能做些什么来使这个工作呢?我知道在整个生成过程完成之前,这个函数不会超出范围。
我是一个新手,所以我可能(也可能是)忘记了很多隐藏在文档深处的概念。我很确定,有一个非常干净和非常类似于 rust 的方法来解决这个问题,但我的思想停留在C++思维中。

kjthegm6

kjthegm61#

不幸的是,我的程序结构不允许我这样做,因为函数中的一些组件的生命周期确实受到主函数的一部分的限制。
这是你需要改变的部分。改变你的程序的 * 那些 * 部分,这样就不会从main()借用任何东西。

  • 使用const s或static变量作为常量数据。
  • 使用Arc而不是&来引用启动时计算的共享数据。
  • 或者如果绝对必要的话(例如当数据不是常量,必须在Copy需求中引用),并且您只打算在启动时执行一次,则使用Box::leak(Box::new(data))来获取对某些数据的&'static引用,这些数据以后将永远不会被释放。除了只计算过一次的数据之外,您不能对任何其他数据使用此方法,因为那样的话,您的程序将真实的意义上的内存泄漏,并且不断增加。

使用scoped threads将借用的数据传递给线程是 * 可能的 *,但这种方法需要对 * 线程 * 进行特殊控制,并且不适用于GUI事件循环或本身没有明确作用域的线程池等情况。
进一步说明:
为什么我需要传递一个静态的生命周期呢?线程的生命周期不会那么长,所有的东西都是直接在下面连接的。
简单:借位检查器并不理解线程连接,它只查看非常特殊的编译时信息,“当调用join()函数时,线程一定已经退出”不是它能够执行的推理类型,广义地说,借款审核员只关心那些“没有”发生事情(“此引用不在此生命周期之外使用”)并且不能使用 do happen的事情,如“join()was called”,作为程序是健全的证据。
我上面提到的“作用域线程”是一种使停止线程 * 为借用检查器 * 所理解的方法--通过使其看起来像退出函数作用域,借用检查器 * 确实 * 将其理解为借用已经明确结束的原因。

相关问题