How to generate random numbers in async rust?
Asked Answered
O

2

5

The rng crate is neither Sync nor Send, so the rng::thread_rng can not cross the .await point. What is the simplest and beautiful way to generate random numbers in async rust?

Generating A lot of numbers beforehead and then use them is ugly.

Order answered 8/5, 2021 at 3:34 Comment(4)
Confusingly, the handle returned by thread_rng seems to compile being transferred across await in this playground example. I'm not sure what's up with that.Elaelaborate
But you could always create your own proper rng, e.g. using let mut rng: StdRng = SeedableRng::from_entropy(), as shown in this answer. That will give you something that is not just a handle to a thread-local and should be Send+Sync.Elaelaborate
@Elaelaborate thanks for the answer. I used StdRng in an async tokio stream and it works flawless.Fulmer
@DanielLeiszen Glad it helped. To answer my own question from the first comment, awaiting a non-send future works in main() because main itself gets run in the main thread, which is why Tokio can get away with not requiring that the future it produces be Send. However, if you try something like tokio::spawn(async { foo().await }), it will fail to compile, as expected.Elaelaborate
L
9

From the tokio Discord server

let random = rand::random::<i64>();

or

let random = {
    let mut rng = rand::thread_rng();
    rng.gen::<i64>()
}

"make sure the rng variable falls out of scope before you use an await"

Lowtension answered 24/1, 2023 at 21:59 Comment(0)
C
1

Getting a new rng handle is cheap. A rng will be created once per thread (when used), and after that ThreadRng::default only uses LocalKey::with and Rc::clone. Do you need to keep the previous state so the number sequence is repeatable?

Chemise answered 8/5, 2021 at 4:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.