Live data from Hacker News

Zig's new plan for asynchronous programs

lwn.net

71–80 of 274 posts

Re: Zig's new plan for asynchronous programs

#71
post #45

Earlier quoted context omitted.

But that can already be done using async await. If you write an async function in Rust for example you are free to call it with any async runtime you want.

But you can't call it from synchronous rust. Zig is moving toward all sync code also using the Io interface.

yes, you can:

    runtime.block_on(async { })
https://play.rust-lang.org/?version=stable&mode=debug&editio...

Re: Zig's new plan for asynchronous programs

#72
post #20
post #14

Earlier quoted context omitted.

One of the harms Go has done is to make people think its concurrency model is at all special. “Goroutines” are green threads and a “channel” is just a thread-safe queue, which Zig has in its stdlib https://ziglang.org/documentation/master/std/#std.Io.Queue

A channel is not just a thread-safe queue. It's a thread-safe queue that can be used in a select call. Select is the distinguishing feature, not the queuing. I don't know enough Zig to know whether you can write a bit of code that says " either pull from this queue or that queue when they are ready"; if so, then yes they are an adequate replacement, if not, no they are not. Of course even if that exact queue is not i…

> I don't know enough Zig to know whether you can write a bit of code that says "either pull from this queue or that queue when they are ready"; if so, then yes they are an adequate replacement, if not, no they are not.

Thanks for giving me a reason to peek into how Zig does things now.

Zig has a generic select function[1] that works with futures. As is common, Blub's language feature is Zig's comptime function. Then the io implementation has a select function[2] that "Blocks until one of the futures from the list has a result ready, such that awaiting it will not block. Returns that index." and the generic select switches on that and returns the result. Details unclear tho.

[1] https://ziglang.org/documentation/master/std/#std.Io.select

[2] https://ziglang.org/documentation/master/std/#std.Io.VTable

Re: Zig's new plan for asynchronous programs

#73
post #56

Earlier quoted context omitted.

The subject of the function coloring article was callback APIs in Node, so an argument you need to pass to your IO functions is very much in the spirit of colored functions and has the same limitations.

In Zig's case you pass the argument whether or not it's asynchronous, though. The caller controls the behavior, not the function being called.

The coloring is not the concrete argument (Io implementation) that is passed, but whether the function has an Io parameter in the first place. Whether the implementation of a function performs IO is in principle an implementation detail that can change in the future. A function that doesn't take an Io argument but wants to call another function that requires an Io argument can't. So you end up adding Io parameters just in case, and in turn require all callers to do the same. This is very much like function coloring.

In a language with objects or closures (which Zig doesn't have first-class support for), one flexibility benefit of the Io object approach is that you can move it to object/closure creation and keep the function/method signature free from it. Still, you have to pass it somewhere.

Re: Zig's new plan for asynchronous programs

#74
post #62

One thing the old Zig async/await system theoretically allowed me to do, which I'm not certain how to accomplish with this new io system without manually implementing it myself, is suspend/resume. Where you could suspend the frame of a function and resume it later. I've held off on taking a stab at OS dev in Zig because I was really, really hoping I could take advantage of that neat feature: configure a device or sub…

Can you create a thread pool consisting of one thread, and suspend / resume the thread?

Re: Zig's new plan for asynchronous programs

#76
post #6

I'm excited to see where this goes. I recently did some io_uring work in zig and it was a pain to get right. Although, it does seem like dependency injection is becoming a popular trend in zig, first with Allocator and now with Io. I wonder if a dependency injection framework within the std could reduce the amount of boilerplate all of our functions will now require. Every struct or bare fn now needs (2) fields/param…

I think a good compromise between a DI framework and having to pass everything individually would be some kind of Context object. It could be created to hold an Allocator, IO implementation, and maybe a Diagnostics struct since Zig doesn't like attaching additional information to errors. Then the whole Context struct or parts of it could be passed around as needed.

Re: Zig's new plan for asynchronous programs

#77
post #13

Earlier quoted context omitted.

> Why IO is more important than "may panic", "uses bounded stack", "may perform allocations", etc.? Rust could use these markers as well.

I agree. But it should be done with a proper effect system, not a pile of ad hoc hacks built on abuse of the type system.

`async` is in the type system. In your mind, how would you mark and bubble up panicky functions, etc.? What would that look like?

I felt like a `panic` label for functions would be nice, but if we start stacking labels it becomes cumbersome:

  pub async panic alloc fn foo() {}
That feels dense.

I think ideally it would be something readers could spot at first glance, not something inferred.

Re: Zig's new plan for asynchronous programs

#78
post #71
post #45

Earlier quoted context omitted.

But you can't call it from synchronous rust. Zig is moving toward all sync code also using the Io interface.

yes, you can: runtime.block_on(async { }) https://play.rust-lang.org/?version=stable&mode=debug&editio...

Here's a problem with that:

    Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.
https://play.rust-lang.org/?version=stable&mode=debug&editio...

Re: Zig's new plan for asynchronous programs

#79
This design seems very similar to async in scala except that in scala the execution context is an implicit parameter rather than an explicit parameter. I did not find this api to be significantly better for many use cases than writing threads and communicating over a concurrent queue. There were significant downsides as well because the program behavior was highly dependent on the execution context. It led to spooky action at a distance problems where unrelated tasks could interfere with each and management of the execution context was a pain. My sense though is that the zig team has little experience with scala and thus do not realize the extent to which this is not a novel approach, nor is it a panacea.

Re: Zig's new plan for asynchronous programs

#80
post #71
post #45

Earlier quoted context omitted.

But you can't call it from synchronous rust. Zig is moving toward all sync code also using the Io interface.

yes, you can: runtime.block_on(async { }) https://play.rust-lang.org/?version=stable&mode=debug&editio...

Let me rephrase, you can't call it like any other function.

In Zig, a function that does IO can be called the same way whether or not it performs async operations or not. And if those async operations don't need concurrency (which Zig expresses separately to asynchronicity), then they'll run equally well on a sync Io runtime.

Post reply on HN