"Maybe we could just have kept Rust as it was circa 2016, and let the crazy non-blocking folks write hand-crafted epoll() loops like they do in C++. I honestly don’t know, and think it’s a difficult problem to solve." I think this is the most underappreciated part of this article. Since when did everything have to be async? There are other ways to represent concurrency that more accurately reflect what the computer i…
> let the crazy non-blocking folks write hand-crafted epoll() loops like they do in C++. > I think this is the most underappreciated part of this article. I think it's incredibly silly actually. Abandon all async for a difficult and error prone epoll model? > Since when did everything have to be async? It doesn't! No one is forcing anyone to use async. I'm not sure why the author implies that. But if you do want to u…
/// A state machine that adds three numbers and uploads them to a web server
struct AddAndUpload {
/// I/O handle to the event loop
io: IOClient,
/// Buffer to store numbers I load
nums: [u64; 3],
/// URL to upload the data to
url: String
}
impl AddAndUpload {
/// Constructor
pub fn new(io: IOClient, url: String) -> AddAndUpload {
AddAndUpload {
io,
nums: [0u64; 3],
url
}
}
/// Entry point to this state machine
pub fn inner_main(&mut self) -> Result {
/// go and get the data
let n1_fut : IOClient::Future = self.io.sql_async("SELECT n1 FROM table1", &[])?;
let n2_fut : IOClient::Future = self.io.sql_async("SELECT n2 FROM table2", &[])?;
let n3_fut : IOClient::Future = self.io.sql_async("SELECT n3 FROM table3", &[])?;
// wait for all I/O operations to finish
IOClient::wait_all(&[&n1_fut, &n2_fut, &n3_fut])?;
// extract results
let n1 = n1_fut.into_inner();
let n2 = n2_fut.into_inner();
let n3 = n3_fut.into_inner();
// upload them
let sum = n1 + n2 + n3;
let upload_fut : IOClient::Future = self.io.http_post_async(&self.url, &["content-type: application/octet-stream"], &sum.to_be_bytes())?;
let upload_http_status = upload_fut.wait()?.into_inner();
match upload_http_status.as_u16() {
200 => {
Ok(())
}
400..499 => {
Err(IOClient::Error::Custom("client error"))
}
500..599 => {
Err(IOClient::Error::Custom("server error"))
}
x => {
Err(IOClient::Error::Custom("Nonsensical HTTP code"))
}
}
}
}
impl IOClient::StateMachine for AddAndUpload {
type Return = ();
fn main(&mut self) -> Result {
self.inner_main()
}
}
/\* somewhere else \*/
fn main() {
let io_server = IOServer::spawn().unwrap();
let io_client = io_server.client().unwrap();
let add_and_upload = AddAndUpload::new(io_client, "http://example.com".to_string());
loop {
io_server.run().unwrap();
match add_and_upload.get_machine_status() {
Ok(IOClient::StateMachine::Finished(result)) => {
eprintln!("add_and_uploaded exited with {:?}", &result);
break;
}
Ok(_) => {},
Err(e) => {
panic!("add_and_upload aborted: {:?}", &e);
}
}
}
io_server.terminate();
}