Comment by bheadmaster

1 year ago

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.