Skip to content

Instantly share code, notes, and snippets.

@nroi
Created February 14, 2022 16:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nroi/16db3e2c667192f4533755b07fd5d2da to your computer and use it in GitHub Desktop.
Save nroi/16db3e2c667192f4533755b07fd5d2da to your computer and use it in GitHub Desktop.
// #![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