Hacker News new | ask | show | jobs
by sifoobar 2752 days ago
I'll take fibers that yield automatically on blocking operations over async/await most days for most tasks. It's slightly less flexible, since you can only wait for one async action at a time per fiber; but a pleasure to use in comparison. But for that you need fibers built in.

Go sort of does the same thing, but insists on running fibers in separate threads at its convenience; which means giving up the lovely simplicity of cooperative multitasking for the same old multi-threaded circus.

I'm unfortunately not aware of any languages more recent than Smalltalk that get this right. My own baby, Snigl [0], is just getting to the point where it's doable.

[0] https://gitlab.com/sifoo/snigl

3 comments

The problem with fibers is interop. The moment you need to do some FFI, especially FFI that involves callbacks, things get a lot more complicated, since code you're calling into/through doesn't have any of that fiber magic (and, depending on how you implemented yours, it might actually break it).
Another win for embedded languages/inside-out FFI in my book, since controlling the outside world (C in Snigl's case) makes it trivial to register a trampoline with whatever state needed to deliver the call.
Sure, but now you need C code that needs to be aware of your trampoline, specifically. Good luck if it's an existing library. Also, what happens if there are multiple interleaved C parts of the stack, and the innermost one invokes the trampoline? What happens to the ones in the middle? It all sounds awfully like setjmp/longjmp (which is the one thing that you never do in C if you want to interoperate with anything in a sane fashion).

And I don't think FFI direction matters much. The moment you have callbacks, your stack has interleaving of languages anyway (i.e. X called into Y which called back into X). Does it really matter which language the innermost and the outermost stack frames belong to? You still need to handle the mix in the middle.

Why? You really only need the C library to be able to pass a data pointer to the callback, and most do.

This sounds like a native compiler perspective to me; with pure VM fibers like Snigl's these are not issues.

It's not about direction, it's about controlling the world from the outside.

You sound more like you're on a mission to prove to the world it's impossible, since Rust didn't manage to get it right.

What happens with all the interleaving stack frames when that callback gets invoked?
Have you given Erlang a look? What it calls processes sound like what you call fibers; although it does have quasi-premptive yielding as well as yielding when waiting for a message. Since Erlang is built on async message passing, you can easily send a request and block on the response, but you can also send multiple requests and process the responses as they arrive.
Sure, I played with Erlang back in the days. Preemptive kills the whole idea, which is why you can't share values. And it's probably the least integrated language I've come across.
Wren and I'm guessing Lua have fibers that work similarly.
Lua has fibers? I thought they settled on throwing coroutines over the fence, which is very much not the same thing even though you can sort of build fibers using them. I'm pretty sure Wren's fibers aren't integrated with the IO-layer, but I'd be happy to be wrong there.