Open coderedart opened 3 years ago
This seems related to https://rust-lang.github.io/wg-async-foundations/vision/unresolved_questions/default_runtime.html. Another option might be to have some sort of basic (i.e. less efficient) cross-platform reference implementation of a runtime in std
, ideally in such a way that it could be optimized into code similar to what you're describing.
i think this article/reddit post explained partially what i wanted to say https://www.reddit.com/r/rust/comments/paqdiy/blog_post_async_overloading/ . i always considered async runtimes to be in rust just like allocators. a core part of rust, but swappable with external ones if needed. or kinda like how people do nostd to avoid pulling in default containers etc... and for people who want to customize, they can do so.
This is also in the roadmap as a possibility to explore: https://rust-lang.github.io/wg-async-foundations/vision/roadmap/async_overloading.html
Brief summary
I will try to write my experience here as a story. I am like Niklaus. interested in programming, could write basic programs.i thought i would make an API crate for a game i play called Guild Wars 2. The game provides the live player data (MumbleLink) like location, camera position/direction etc.. via shared memory. I run my game in wine and I wanted to expose it via a local server so other addons/overlays (which run on linux natively) can just use it as a library. and i would also support requesting data from servers about skills or other data which can be used by addons or web apps with seed.rs or yew.rs .
First, i wanted to deal with the shared memory. and as rust was a low level language and with winapi crate, it was really easy. for server, first i used std's udpsocket. was really easy too. but i thought i should expose a more proper api and i wanted to use grpc as its purely binary protocol. i choose tonic-rs to implement a grpc server. i was on windows and everything was working great. i boot to linux and find out that it crashes in wine. after a full day of debugging with println! statements, i see that mio was the crash reason. i find out that https://github.com/tokio-rs/mio/issues/1444 , wine and haiku OS are not supported by mio. after reading about the usage of undocumented/legacy api, the first question i had was "why am i wasting so much time with this? this is not fun at all" and just gave up.there is only so much time/energy i can spend on any given hobby.
Second, i wanted to work on the api part of the crate. the question that popped up was, what to use as http client? because if i use a async client, i can't use it on wine. and if i use blocking, it is useless for web applications as a library. so... now i need to find a crate which supports both blocking and async clients, which can be turned on/off with feature gating. and obviously the popular crate called reqwest supports it. i tried to use it, and wine crashes. war flashbacks of debugging tonic. i immediately go into the source code to find that under the blocking api, reqwest actually has a async api. searching since forever, but there's either a async crate that exposes a thing blocking wrapper or a crate that's purely blocking. again, i was thinking that this was not fun. rust has tiered platform support. but rust async support is decided by third party crates and not rust itself as there's no official runtime.
So, i wondered. if i have to support both webapp and desktop /wine usage, do i need to write all api calls twice and feature gate async/blocking apis? for something so simple like making a request, what even is the difference?
and ofcourse, that's when i thought.
make_request().await
. if i have a runtime like tokio/asyncstd/smol, the compiler can use it as a state machine and swtich to other threads/tasks. but when there's no runtime, why can't the compiler just compile the function into a blocking code like ureq? if we had the ability to compile the async functions into blocking functions, i don't have to write my api twice with a [cfg(feature(async))] on all of the functions. and there will be no need for something like async-std to exist, as the whole std library can be made async and still be used by the programs as usual in a blocking manner. i am a newbie programmer and do not know what happens behind the scenes with futures or pins or all those fancy words. all i an think of is that for a long of common cases, writing func_call().await is just blocking code and join!(func_call().await, func_call2.await()) is parallel code like rayon's threadpool.Optional details
(Optional) Which [character(s)] would be the best fit and why?
(Optional) What are the key points or morals to emphasize?
finally, i want to apologize in advance if i wasted people's time with this ridiculous idea. I have no idea about the intricate differences between async and sync execution models. what i am proposing might not be possible. this is just something i thought would be super cool for newbie rust programmers. just switching between async/sync rust binaries with a cargo option or such would make a lot of QoL improvements for library authors that want to support blocking and async apis.