比较 Rust 中异步操作的句柄与流。

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

Comparing handles vs streams for async operations in rust

问题

In rust, we can write a vector of handles that allows to have asynchronous operation without blocking:

use tokio;

#[derive(Clone)]
struct Cont {
    delta: usize,
}

impl Cont {
    fn get(&mut self) -> usize {
        self.delta
    }
}

#[tokio::main]
async fn main() {
    let delta = 3;
    let cont = Cont { delta };
    let mut handles = Vec::new();
    for i in 0..10 {
        let mut cont = cont.clone();
        handles.push(tokio::spawn(async move {
            cont.get() + i.clone()
        }));
    }
    let _response = futures::future::join_all(handles).await;
}

But this builds a vector of handles which might be considered a negative.

The stream version would replace the main with

#[tokio::main]
async fn main() {
    let delta = 3;
    let cont = Cont { delta };
    let stream = stream::iter(0..10).then(|i| async move {
        cont.clone().get() + i.clone()
    });
    let _result : Vec<usize> = stream.collect().await;
}

Unfortunately, it does not compile.

So my questions are the following:

  • Is it possible to have the stream version of the code working correctly, that is, is there a way to clone the cont?
  • Apart from the building of a vector of handles, which does not occur in the stream version, are both versions the same? I mean, are they both based on green threads?
英文:

In rust, we can write a vector of handles that allows to have asynchronous operation without blocking:

use tokio;

#[derive(Clone)]
struct Cont {
    delta: usize,
}

impl Cont {
    fn get(&amp;mut self) -&gt; usize {
        self.delta
    }
}

#[tokio::main]
async fn main() {
    let delta = 3;
    let cont = Cont { delta };
    let mut handles = Vec::new();
    for i in 0..10 {
        let mut cont = cont.clone();
        handles.push(tokio::spawn(async move {
            cont.get() + i.clone()
        }));
    }
    let _response = futures::future::join_all(handles).await;
}

But this builds a vector of handles which might be considered a negative.

The stream version would replace the main with

#[tokio::main]
async fn main() {
    let delta = 3;
    let cont = Cont { delta };
    let stream = stream::iter(0..10).then(|i| async move {
        cont.clone().get() + i.clone()
    });
    let _result : Vec&lt;usize&gt; = stream.collect().await;
}

Unfortunately, it does not compile.

So my questions are the following:

  • Is it possible to have the stream version of the code working correctly, that is, is there a way to clone the cont?
  • Apart from the building of a vector of handles, which does not occur in the stream version, are both versions the same? I mean, are they both based on green threads?

答案1

得分: 1

Sure, here's the translated code portion:

是的,可以做到:

fn main() {
    let delta = 3;
    let cont = Cont { delta };
    let stream = futures::stream::iter(0..10).then(move |i| {
        let mut cont = cont.clone();
        async move { cont.get() + i.clone() }
    });
    let _result: Vec<usize> = stream.collect().await;
}

基本上只需在闭包中克隆 cont,然后将其移动到异步块中。

是的,它们在功能上是等效的。

英文:

Yup, it's doable:

fn main() {
    let delta = 3;
    let cont = Cont { delta };
    let stream = futures::stream::iter(0..10).then(move |i| {
        let mut cont = cont.clone();
        async move { cont.get() + i.clone() }
    });
    let _result: Vec&lt;usize&gt; = stream.collect().await;
}

Basically just clone the cont in the closure and then move it to the async block.

And yes, they are functionally equivalent.

huangapple
  • 本文由 发表于 2023年5月13日 19:52:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76242578.html
匿名

发表评论

匿名网友

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

确定