3 ms·
> it creates plenty of complexity wrt. e.g. interfacing with other languages Hmm I'm not sure I get this point. Do you mean in comparison with async? Async cro
by klabb3 5y ago
> it creates plenty of complexity wrt. e.g. interfacing with other languages
Hmm I'm not sure I get this point. Do you mean in comparison with async? Async cross language interfaces should need the same type of continuation mechanisms (eg poll or completion based interop with an event loop) as green threads, no? I think of async as a primarily syntactically explicit construction, while both look similar in ABI, with a virtual stack. If not, I'd love to know why.
- int_19h 5y agoAsync with explicit await is basically just syntactic sugar for continuation callbacks. The "virtual stack" that results can thus be expressed entirely in terms that the C ABI understands: a callback is just a C function pointer + pointer to the struct representing the virtual stack frame.
- klabb3 5y agoSure, but then the callee is responsible for any async io anyways - meaning it needs to either run its own event loop or use a thread pool if it wants to do IO, right? What I mean is that without a protocol/ABI to access the caller's runtime, you'd have to use your own. For instance, Rust has explicit async/await but the poll method has a pointer to a waker, and a non-standard global/thread local variable is used to communicate with the runtime. Specifically it needs to access the reactor (in Rust lingo).
- int_19h 5y agoIt depends. You can treat it as implementation detail, with multiple loops if needed. Or you can use a shared event loop propagated over the same C ABI. Either way, this all maps nicely to C FFI. But true green threads don't - since every frame is interruptible by default, all languages involved must use the async stack for all functions, in a way that's compatible with them all. Like tail calls, this is an ABI-level thing that you can't slap on top of the existing C ABI.
- klabb3 5y agoAh! Finally I think I'm getting the distinction, thanks for being patient. I also agree about the ABI issue - explicit callbacks is much simpler. It appears as Go doesn't expose green threads as per your definition for it's FFI though, but rather an even simpler synchronous interface in both directions. This makes it impossible to interface with the event loop, and one must use threads. For Go->C, at least, this should not block the runtime since the Go runtime spins up more threads in case of long running synchronous calls (their version of pre-emption).
- int_19h 5y agoFor an opposite example, consider async/await in C# - you're not restricted to .NET when using it; it also supports e.g. the native async OS APIs in WinRT (which are callback-based on ABI level: https://docs.microsoft.com/en-us/uwp/api/windows.foundation.iasyncinfo https://docs.microsoft.com/en-us/uwp/api/windows.foundation....). Ditto for co_await in C++20. Go's approach leads to an insular ecosystem that tends to reimplement everything, because that's the only way to get this transparent async throughout.