Created
February 14, 2022 16:18
-
-
Save nroi/16db3e2c667192f4533755b07fd5d2da to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// #![deny(warnings)] | |
use std::time::Duration; | |
use futures::executor::block_on; | |
use std::net::{TcpListener, TcpStream}; | |
use std::sync::atomic::{AtomicUsize, Ordering}; | |
static REQUEST_COUNT: AtomicUsize = AtomicUsize::new(0); | |
#[tokio::main] | |
async fn main() { | |
let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); | |
for client_stream in listener.incoming() { | |
// we generally assume that the number of concurrent requests is low (not more than a few dozen), so we are | |
// willing to pay the price of having one separate thread for each incoming request. In addition, we need to use | |
// blocking IO, so we have a good reason for doing so. | |
tokio::task::spawn_blocking(move || { | |
let request_num = REQUEST_COUNT.fetch_add(1, Ordering::SeqCst); | |
println!("Start processing request {}", request_num); | |
// process_request calls async functions, so we start an async-block here: | |
let future = async { | |
process_request(client_stream.unwrap()).await; | |
}; | |
// block_on is often discouraged, but hopefully, this is a valid use case for it? | |
block_on(future); | |
println!("Finished processing request {}", request_num); | |
}); | |
} | |
} | |
async fn process_request(_client_stream: TcpStream) { | |
// Processing the request requires functions such as tokio's timeout. So something purely based | |
// on threads, without tokio and without async, is not viable. | |
match tokio::time::timeout(Duration::from_secs(10), fetch_resource_async()).await { | |
Ok(_) => {} | |
Err(_timeout) => { | |
println!("Unable to fetch resource within the given timeout."); | |
} | |
} | |
fetch_resource_blocking_io(); | |
} | |
async fn fetch_resource_async() { | |
tokio::time::sleep(Duration::from_secs(2)).await; | |
} | |
fn fetch_resource_blocking_io() { | |
// Just imagine that this function is doing blocking IO, and we don't have the option to turn that into | |
// non-blocking IO. | |
std::thread::sleep(Duration::from_secs(5)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment