传递结构体给Rust线程

huangapple go评论77阅读模式
英文:

Passing structs to threads in rust

问题

我有一个函数,接受一个相对较大的结构体的引用。该函数使用tokio生成一些线程,这些线程将接收该结构体。这些线程都不需要修改结构体。

这是一个假设的例子:

   #[tokio::main]
    async fn search(&self, struct_a: Arc<StructA>) {
        for i in 0..10 {
            task::spawn(async move {
                // 对struct_a 进行操作
            });
        }
    }

如果我只是将引用传递给线程,Rust 将抱怨我试图移动一个已借用的值,这是有道理的。所以我认为我的选择有:

  1. 克隆实际的结构体并将其传递给线程。这很昂贵。
  2. 使函数接受一个 Arc<StructA>,然后调用 arcOfA.clone() 并将其传递给线程。这将避免克隆实际的结构体,并应该解决已借用值的问题。

还有其他选择吗?我对此的考虑是否正确?

英文:

I have a function that takes in a reference to a relatively big struct. The function spawns a few threads using tokio that will take in the struct. None of the threads need to modify the struct.

This is a contrived example:

   #[tokio::main]
    async fn search(&amp;self, struct_a: Arc&lt;StructA&gt;) {
        for i in 0..10 {
            task::spawn(async move {
                // do something with struct_a
            });
        }
    }

If I just pass the references to the thread rust will complain that I am trying to move a borrowed value, which makes sense. So this is what i think my options are:

  1. Clone the actual struct and pass it to the thread. This is expensive.
  2. Have the function take in a Arc&lt;StructA&gt;, and then calling arcOfA.clone() and pass that to the thread. This will avoid cloning the actual struct and should solve the borrowed value issue

Any other option? Am I thinking about this correctly?

答案1

得分: 1

你的两个想法都是正确的(尽管克隆结构的费用不应被过分估计,这取决于结构中包含的内容以及其大小)。

但根据你在各个任务中的操作,你还可以创建简单的futures,并将它们通过join!()组合成一个单一的future(更可能是通过类似 FuturesOrderedjoin_all 的方式)。如果工作主要涉及线程IO而且CPU工作相对较少,这应该没问题。

如果你一直在使用普通线程,我会建议使用scoped threads,但你没有。有一个async-scoped,但显然它在本质上是相当受限的,因为它基本上是为了安全性的原因而繁忙等待

英文:

Your two ideas are correct (though the expense of cloning the struct should not be overestimated, it depends what's in the structure and how large it is).

But depending what you do in the individual tasks you might also be able to create simple futures and join!() them together as a single one (more likely via something like FuturesOrdered or join_all though). If the work is primarily threading IO and there's relatively little CPU work it should be fine.

If you'd been using regular threads I'd have suggested scoped threads, but you're not. There's an async-scoped but apparently it's pretty limiting as it essentially busy waits for soundness reasons.

huangapple
  • 本文由 发表于 2023年3月7日 01:35:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75654044.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定