I ran into the kind of a problem described in this question: How can I create a Tokio runtime inside another Tokio runtime without getting the error "Cannot start a runtime from within a runtime"? .
Some good rust crates doesn't have asynchronous executor. I decided to put all such libraries calls in one thread which is tolerant of such operations. Another thread should be able to send non-blicking messages using tokio::channel
.
I have programmed a demo stand to test implementation options. Call tokio::spawn
inside of each runtime is made in order to understand a little more detail in tokio runtimes and handlers - it is a part of a question.
The question.
Please correct me if I misunderstand something further.
There are two tokio runtimes. Each is launched in its own thread. Call tokio::spawn
inside first_runtime()
spawns task on first runtime. Call tokio::spawn
inside second_runtime()
spawns task on second runtime. There is a tokio::channel
between these two tasks. Call tx.send(...).await
does not block sending thread if channel buffer is not full, even if receiving thread is blocked by thread::sleep()
call.
Am I getting everything right? The output of this code tells me that I'm right, but I need confirmation of my reasoning.
use std::thread;
use std::time::Duration;
use tokio::sync::mpsc::{Sender, Receiver, channel}; // 1.12.0
#[tokio::main(worker_threads = 1)]
#[allow(unused_must_use)]
async fn first_runtime(tx: Sender<String>) {
thread::sleep(Duration::from_secs(1));
println!("first thread woke up");
tokio::spawn(async move {
for msg_id in 0..10 {
if let Err(e) = tx.send(format!("message {}", msg_id)).await {
eprintln!("[ERR]: {}", e);
} else {
println!("message {} send", msg_id);
}
}
}).await;
println!("first thread finished");
}
#[tokio::main(worker_threads = 1)]
#[allow(unused_must_use)]
async fn second_runtime(mut rx: Receiver<String>) {
thread::sleep(Duration::from_secs(3));
println!("second thread woke up");
tokio::spawn(async move {
while let Some(msg) = rx.recv().await {
println!("{} received", msg);
}
}).await;
println!("second thread finished");
}
fn main() {
let (tx, rx) = channel::<String>(5);
thread::spawn(move || { first_runtime(tx); });
second_runtime(rx);
}