Comment by cmrx64

1 year ago

I’ve recently (past year) been diving deep into async Rust and the modern Rust ecosystem after a several year hiatus (last active 2013-2016, pre-async). maybe this advice applies to a small category of application developers, but this take overall feels reactionary (versus constructive) and immature (cites OS primitives that don’t approach the same design space). There are pains with async Rust but the community should lean into trying to solve them. I personally don’t feel the pains as severely as described…

Deferred computation is a primitive, and threads do not solve it.

I feel that, from a language theory level, it should be possible to implement functions that can be called in both sync and async contexts, removing the need for function coloring.

Any fundamentally blocking operations could be forced by the compiler to have have two implementations - sync (normal) and async, which defers to some abstract userspace scheduler that's part of the language itself.

  • Something like … being explicitly polymorphic over some monad? :)

    The choice and ordering and soforth of yield points / poll order really drastically can change the semantics of your program. But if you don’t care..

  • > it should be possible to implement functions that can be called in both sync and async contexts, removing the need for function coloring.

    It is possible! They're called blue (sync) functions.

    • Sync functions that block (e.g. perform a system call) cannot be called from async functions.

      (Actually, they can, but you're going to stop the whole scheduler, or at least one of its worker threads, which is something you really don't want to do...)

  • >it should be possible to implement functions that can be called in both sync and async contexts

    You still have concurrency or interleaved execution to contend with but that could be represented more explicitly since it's not unique to async.

    I haven't done much rust but implementing blocking operations as async functions is commonly achieved in Python by using threads under the hood anyway

  • I believe Java virtual threads/project Loom fits what you are describing. No separate async APIs, everything is coded using a thread based model. The user decides between using platform/OS threads (thus delegating scheduling to the kernel), or using virtual threads and letting the JVM take over scheduling.

    • Yes, Go also fits what I'm describing.

      But I was wondering if the same thing could be brought to Rust, while still keeping the runtime away from the language. I probably forgot to mention Rust in the grandparent comment.