Conversation
| /// Copied and then passed to `start`. | ||
| context: []const u8, | ||
| context_alignment: std.mem.Alignment, | ||
| start: *const fn (*Group, context: *const anyopaque) void, |
There was a problem hiding this comment.
Is there a particular reason for passing the *Group as a separate parameter to start (which is not needed by the majority of call sites) instead of just having Select(...).async add it to the args in context?
There was a problem hiding this comment.
maybe I'm not understanding the suggestion, but that kind of sounds like a pain in the ass and unclear that it will generate better code
lib/std/Io.zig
Outdated
|
|
||
| /// `s` is a struct with every field a `*Future(T)`, where `T` can be any type, | ||
| /// and can be different for each field. | ||
| pub fn select(io: Io, s: anytype) SelectUnion(@TypeOf(s)) { |
There was a problem hiding this comment.
| pub fn select(io: Io, s: anytype) SelectUnion(@TypeOf(s)) { | |
| pub fn select(io: Io, s: anytype) Cancelable!SelectUnion(@TypeOf(s)) { |
The doc comment for select should also probably be updated to describe when error.Canceled is returned. Based on my own understanding of how select should behave, maybe something like /// Returns `error.Canceled` if all futures in `s` are canceled. would work?
9c20f4f to
477c939
Compare
|
What happened to std.Io.AsyncDetached/goroutines? I remember that being a core feature back when this design was first proposed. |
This comment was marked as resolved.
This comment was marked as resolved.
|
So what would be the equivalent Zig code for package main
import (
"fmt"
)
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
close(c)
}
func main() {
c := make(chan int, 10)
go fibonacci(cap(c), c)
for i := range c {
fmt.Println(i)
}
}(Taken from: https://go.dev/tour/concurrency/4 ) |
|
@ValorZard that's actually a great example of a flaw with So, a "direct" port of your code would look like this: //! This example omits the creation of the `Io` instance for brevity.
fn fibonacci(n: usize, q: *Io.Queue(u64), io: Io) !void {
var x: u64 = 0;
var y: u64 = 1;
for (0..n) |_| {
try q.putOne(x);
const new = x + y;
x = y;
y = new;
}
}
pub fn main(io: Io) !void {
// This is the "detach" group; you run tasks in this group if you just want them to clean
// themselves up upon completion. There is just one of these across the entire application.
var group: Io.Group = .init;
errdefer _ = group.cancel();
try mainInner(io, &group));
try group.wait();
}
fn mainInner(io: Io, group: *Io.Group) !void {
const n = 10;
var q_buf: [n]u64 = undefinedl
var q: Io.Queue(u64) = .init(&q_buf);
try group.concurrent(io, fibonacci, .{ n, &q, io });
for (0..n) |_| {
std.debug.print("{d}\n", .{try q.getOne(io)});
}
}But looking at that, the redundant work I was talking about becomes blindingly obvious: I mean, we're making a group with only one task, and we obviously know when it finishes! So, we could rewrite it as follows: fn fibonacci(n: usize, q: *Io.Queue(u64), io: Io) !void {
var x: u64 = 0;
var y: u64 = 1;
for (0..n) |_| {
try q.putOne(x);
const new = x + y;
x = y;
y = new;
}
}
pub fn main(io: Io) !void {
const n = 10;
var q_buf: [n]u64 = undefinedl
var q: Io.Queue(u64) = .init(&q_buf);
const fib = try io.concurrent(fibonacci, .{ n, &q, io });
defer fib.cancel() catch {};
for (0..n) |_| {
std.debug.print("{d}\n", .{try q.getOne(io)});
}
}This code is strictly better---it's logically simpler, with obvious lifetimes which both helps you read the code and helps the |
|
Disabling wasm32 backend coverage for test-cases due to this failure: Coverage can be reinstated when wasm backend is further along. cc @pavelverigo |
|
Yay! New IO! |
|
This needs a dedicated design page on zig website. |
Introduced in ziglang/zig#25592 Signed-off-by: Pablo Alessandro Santos Hugen <phugen@redhat.com>
`test/tests.zig` fails after ziglang/zig#25592 was merged in. This just ensures that Io is passed, it might not be the ideal solution. `build.zig` was also failing due to new color parameter.
`test/tests.zig` fails after ziglang/zig#25592 was merged in. This just ensures that Io is passed, it might not be the ideal solution. `build.zig` was also failing due to new color parameter.
`test/tests.zig` fails after ziglang/zig#25592 was merged in. This just ensures that Io is passed, it might not be the ideal solution. `build.zig` was also failing due to new color parameter.
`test/tests.zig` fails after ziglang/zig#25592 was merged in. This just ensures that Io is passed, it might not be the ideal solution. `build.zig` was also failing due to new color parameter.
`test/tests.zig` fails after ziglang/zig#25592 was merged in. This just ensures that Io is passed, it might not be the ideal solution. `build.zig` was also failing due to new color parameter.
This patchset adds
std.Ioand provides two implementations for it:-fno-single-threaded- supports concurrency and cancellation.-fsingle-threaded- does not support concurrency or cancellation.std.IoAPI.std.Io.Threadedhas networking and file-system operations implemented.Cancellation works beautifully, except for a known race condition that has a
couple of competing solutions already in mind.
All of
std.nethas been deleted in favor ofstd.Io.net.std.fshas been partially updated to usestd.Io- only as required so thatstd.Io.Writer.sendFilecould use*std.Io.File.Readerrather than*std.fs.File.Reader.closes #8224
Laundry List of Io Features
async/await- these primitives express that operations can be doneindependently, making them infallible and support execution on limited Io
implementations that lack a concurrency mechanism.
concurrent- same asasyncexcept communicates that the operationmust be done concurrently for correctness. Requires memory allocation.
cancel- equivalent toawaitexcept also requests the Io implementationto interrupt the operation and return
error.Canceled.std.Io.Threadedsupports cancellation by sending a signal to a thread, causing blocking
syscalls to return
EINTR, giving a chance to notice the cancellation request.select- API for blocking on multiple futures usingswitchsyntaxGroup- efficiently manages many async tasks. Supports waiting for andcancelling all tasks in the group together.
Queue(T)- Many producer, many consumer, thread-safe, runtime configurablebuffer size. When buffer is empty, consumers suspend and are resumed by
producers. When buffer is full, producers suspend and are resumed by consumers.
TypeErasedQueue.Select- for blocking on runtime-known number of tasks and handling asubset of them.
Clock,Duration,Timestamp,Timeout- type safety for units of measurementMutex,Condition- synchronization primitivesDemo
Here is an example that makes an HTTP request to a domain:
Thanks to the fact that networking is now taking advantage of the new
std.Iointerface,this code has the following properties:
returned IP address.
attempts are canceled, including DNS queries.
-fsingle-threadedeven though theoperations happen sequentially.
You can see how this is implemented in
std.Io.net.HostName.connect:Upgrade Guide
Missing
ioParameterIf you need an
ioparameter, and you don't have one, you can get one like this:This is legal as long as these functions are not called:
Io.VTable.concurrentThis is a non-ideal workaround - like reaching for
std.heap.page_allocatorwhenyou need an
Allocatorand do not have one. Instead, it is better to accept anIoparameter if you need one (or store one on a context struct for convenience).Point is that the application's
mainfunction should generally be responsible forconstructing the
Ioinstance used throughout.When you're testing you can use
std.testing.io(much likestd.testing.allocator).How to use async/await
Use this pattern to avoid resource leaks and handle cancellation gracefully:
If the
fooorbarfunction does not return a resource that must be freed, then theifcan be simplified to_ = foo() catch {}, and if the function returnsvoid, then the discard can also be removed. Thecancelis necessary however because it releases the async task resource when errors (includingerror.Canceled) are returned.Related
Followup Issues
netLookup#25740netLookup#25741netLookup#25742netLookup#25743HostName.lookupandHostName.connect#25744max_iovecs_lentoIo#25750checkCanceland syscall) #25751std.process.ChildAPI intostd.Io#25752writeResolutionQuery#25754