(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++思维中。
1条答案
按热度按时间kjthegm61#
不幸的是,我的程序结构不允许我这样做,因为函数中的一些组件的生命周期确实受到主函数的一部分的限制。
这是你需要改变的部分。改变你的程序的 * 那些 * 部分,这样就不会从
main()
借用任何东西。const
s或static
变量作为常量数据。Arc
而不是&
来引用启动时计算的共享数据。Copy
需求中引用),并且您只打算在启动时执行一次,则使用Box::leak(Box::new(data))
来获取对某些数据的&'static
引用,这些数据以后将永远不会被释放。除了只计算过一次的数据之外,您不能对任何其他数据使用此方法,因为那样的话,您的程序将真实的意义上的内存泄漏,并且不断增加。使用scoped threads将借用的数据传递给线程是 * 可能的 *,但这种方法需要对 * 线程 * 进行特殊控制,并且不适用于GUI事件循环或本身没有明确作用域的线程池等情况。
进一步说明:
为什么我需要传递一个静态的生命周期呢?线程的生命周期不会那么长,所有的东西都是直接在下面连接的。
简单:借位检查器并不理解线程连接,它只查看非常特殊的编译时信息,“当调用
join()
函数时,线程一定已经退出”不是它能够执行的推理类型,广义地说,借款审核员只关心那些“没有”发生事情(“此引用不在此生命周期之外使用”)并且不能使用 do happen的事情,如“join()
was called”,作为程序是健全的证据。我上面提到的“作用域线程”是一种使停止线程 * 为借用检查器 * 所理解的方法--通过使其看起来像退出函数作用域,借用检查器 * 确实 * 将其理解为借用已经明确结束的原因。