Join a dynamic number of futures [duplicate] - rust

This question already has answers here:
How to wait for a list of async function calls in Rust?
(5 answers)
Closed 3 months ago.
join! can join multiple async operations:
#![feature(future_join)]
use std::future::join;
async fn one() -> usize { 1 }
async fn two() -> usize { 2 }
let x = join!(one(), two()).await;
assert_eq!(x, (1, 2));
Is there a way to join multiple futures from a vector, such that the number of async calls is dynamic (unknown at compile time)?

You can use join_all from the futures crate.
From the docs:
use futures::future::join_all;
async fn foo(i: u32) -> u32 { i }
let futures = vec![foo(1), foo(2), foo(3)];
assert_eq!(join_all(futures).await, [1, 2, 3]);

Related

rust: integer multiplication in match [duplicate]

This question already has answers here:
Why is this match pattern unreachable when using non-literal patterns?
(1 answer)
How do I match based on a dynamic variable?
(4 answers)
How can I store a pattern in a variable in Rust?
(1 answer)
Closed 22 days ago.
Hi I am learnig rust and doing the excercise rustlings/itertors3.rs
My first implementation of fn divide not behaves as I expected. Could Someone explain me why?
My first attempt was:
// Calculate `a` divided by `b` if `a` is evenly divisible by `b`.
// Otherwise, return a suitable error.
pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
let res = a.checked_div(b).ok_or(DivisionError::DivideByZero)?;
match res*b {
a => Ok(res),
other => Err(DivisionError::not_evenly_dividable(a, b))
}
}
But this gives a false positive. This works:
pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
let res = a.checked_div(b).ok_or(DivisionError::DivideByZero)?;
match a%b {
0 => Ok(res),
other => Err(DivisionError::not_evenly_dividable(a, b))
}
}
Why?

Rust: how to perform heavy amount of concurrency in a loop?

Supposing I have calculation like:
async fn sum_2(x: &f64) -> f64 {
x + 2
}
fn main() {
let mut x = vec![
vec![1.0, 2.0, 3.0],
vec![2.0, 3.0, 4.0],
];
for i in 0..2 {
for j in 0..3 {
x[i][j] = sum_2(x[i][j]).await;
}
}
}
What is the right/better way of performing this concurrently?
I am aware of join!(), which is excellent when the calls are known.
I also know the thread::spawn(), but I don't know if this is the right tool for achieving this, nor how. Isn't there something like a pool of threads in Rust that I could send all function calls into and then execute? Thanks!
Looks like you're looking for futures::future::join_all.
From the official example:
use futures::future::join_all;
async fn foo(i: u32) -> u32 { i }
let futures = vec![foo(1), foo(2), foo(3)];
assert_eq!(join_all(futures).await, [1, 2, 3]);

How to convert a 4 element &[u8] into i32? [duplicate]

This question already has answers here:
How can I convert a buffer of a slice of bytes (&[u8]) to an integer?
(4 answers)
Closed 1 year ago.
I have an i32 that i pass to my keyvalue database.
let a = 1234i32;
db.put(&a.to_be_bytes());
But i get it back as &[u8], how to convert it back to i32?
update: this example pretty much does what i want.
use std::convert::TryInto;
fn read_be_i32(input: &[u8]) -> i32 {
i32::from_be_bytes(input.try_into().unwrap())
}
Use i32::from_be_bytes and from this answer, TryFrom:
use std::convert::TryFrom;
fn main() {
let a = 1234i32.to_be_bytes();
let a_ref: &[u8] = &a;
let b = i32::from_be_bytes(<[u8; 4]>::try_from(a_ref).expect("Ups, I did it again..."));
println!("{}", b);
}
Playground

Why does futures::join of two executions of thread::sleep not run in parallel? [duplicate]

This question already has answers here:
Why does Future::select choose the future with a longer sleep period first?
(1 answer)
How to run multiple futures that call thread::sleep in parallel? [duplicate]
(1 answer)
Closed 2 years ago.
Cannot seem to get the futures:join macro to execute in parallel using tokio::main.
Cargo.toml
[dependencies]
futures = "0.3"
tokio = { version = "1", features = ["full"] }
main.rs
use futures::join;
use std::time::{Duration, Instant};
use std::thread;
async fn do_io() { thread::sleep(Duration::from_millis(250)); }
async fn fetch() -> ((), ()) {
join!(do_io(), do_io())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let s = Instant::now();
fetch().await;
let d = s.elapsed();
println!("{:?}", d);
Ok(())
}
Expected Output
~250ms
Actual Output
~500ms

Why does multithreaded execution not work when the subroutine is expensive? [duplicate]

This question already has an answer here:
Why are my Rust threads not running in parallel?
(1 answer)
Closed 3 years ago.
This program randomly prints the index number such as 1, 4, 2, 3, 100 ....
use std::thread;
fn main() {
for x in 0..100 {
print!("{}: {:?} ", x, child.join());
}
}
However, once I add the ping() function, which does something other than console output, it no longer executes concurrently, instead just iterating the ping() function.
extern crate serde;
extern crate serde_derive;
extern crate reqwest;
use reqwest::Client;
use std::thread;
use std::process::Command;
fn main() {
for x in 0..100 {
let child = thread::spawn(move || {
ping(x);
});
print!("{}: {:?} ", x, child.join());
}
}
fn ping(x: i32) {
let output = if cfg!(target_os = "windows") {
Command::new("cmd")
.args(&["/C", "echo hello"])
.output()
.expect("failed to execute process")
} else {
Command::new("sh")
.arg("-c")
.arg("https://keisugano.blogspot.com/")
.output()
.expect("failed to execute process")
};
println!("{:?}", output);
}
What is the root cause of this and how do I fix it?
The first example is incomplete without actually spawning threads, so not sure what happened there.
The key point here is that join is blocking, meaning it won't return until the underlying thread is completed. From the documentation:
pub fn join(self) -> Result<T>
Waits for the associated thread to finish.
In terms of atomic memory orderings, the completion of the associated thread synchronizes with this function returning. In other words, all operations performed by that thread are ordered before all operations that happen after join returns.
With this new knowledge, it is clear that what your code actually did was: create a new thread, wait for it to its completion, and then create the next one. So it is still sequntial and clearly not what you intended.
The solution is straightforward: create all the threads first, then wait them to finish as showed below:
use std::thread;
fn main() {
let handles = (0..100)
.into_iter()
.map(|x| {
thread::spawn(move || {
ping(x);
})
})
.collect::<Vec<_>>();
for thread in handles {
thread.join().unwrap();
}
}
fn ping(x: i32) {
// Do things.
}

Resources