-1

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?
  • You haven't `use`d any `stream` so it's not clear what `stream::iter` is. Also, `use tokio;` is redundant. – cdhowie May 13 '23 at 12:24

1 Answers1

0

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<usize> = 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.

IcyTv
  • 405
  • 4
  • 12