Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async going blocking mode when there's no runtime #221

Open
coderedart opened this issue Jul 1, 2021 · 3 comments
Open

Async going blocking mode when there's no runtime #221

coderedart opened this issue Jul 1, 2021 · 3 comments
Labels
good first issue Good for newcomers help wanted Extra attention is needed status-quo-story-ideas "Status quo" user story ideas

Comments

@coderedart
Copy link

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 tokio-rs/mio#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?

    • [* ] [Niklaus]: new programmer from an unconventional background
      Because he doesn't know much about the deeper issues of async/sync execution models and is more interested in doing safe correct projects with a faster language like rust without having to worry about the lower level details.
  • (Optional) What are the key points or morals to emphasize?

    • an official runtime in rust std would help act as a reference implementation that would have much more support by platforms such as haiku OS or wine. when 90% of the async ecosystem uses mio and people like me have to debug for hours before knowing that inside the dependency tree there's mio that doesn't work on wine. multiple unofficial runtimes will just make it worse.
    • a newbie making a very simple api crate should not have to choose between writing double apis for blocking/async or choosing one and dropping other. async functions should degrade into normal functions, atleast the normal simple ones that just making a get request or read a file etc.. just like borrow checker can deal with lifetime elision, there could be a compiler check to error if the async function can't be downgraded.

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.

@coderedart coderedart added good first issue Good for newcomers help wanted Extra attention is needed status-quo-story-ideas "Status quo" user story ideas labels Jul 1, 2021
@sollyucko
Copy link

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.

@coderedart
Copy link
Author

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.

@tmandry
Copy link
Member

tmandry commented Sep 8, 2021

This is also in the roadmap as a possibility to explore: https://rust-lang.github.io/wg-async-foundations/vision/roadmap/async_overloading.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers help wanted Extra attention is needed status-quo-story-ideas "Status quo" user story ideas
Projects
None yet
Development

No branches or pull requests

3 participants