Future of Io.Future

I will start by proclaiming my love for the upcoming std.Io implementation, the famous Io.async, and the equally exciting, yet underrated Io.concurrent. The idea of storing a std.Io.Future is what I am most eager to " try await() ".

So I tried replicating it…

Is it true that every new type of future will induce a new binary version of the function Io.async or Io.concurrent ?? I could not seem to comeup with a non-template (generic) way to return the future without having to type-erase the future’s result itself. I feel like there is something pretty obvious that I am missing here. Or do I just have an irrational fear of generics?

It’s only a thin wrapper to provide type safety around a type-erased function:

pub fn concurrent(
    io: Io,
    function: anytype,
    args: std.meta.ArgsTuple(@TypeOf(function)),
) ConcurrentError!Future(@typeInfo(@TypeOf(function)).@"fn".return_type.?) {
    const Result = @typeInfo(@TypeOf(function)).@"fn".return_type.?;
    const Args = @TypeOf(args);
    const TypeErased = struct {
        fn start(context: *const anyopaque, result: *anyopaque) void {
            const args_casted: *const Args = @ptrCast(@alignCast(context));
            const result_casted: *Result = @ptrCast(@alignCast(result));
            result_casted.* = @call(.auto, function, args_casted.*);
        }
    };
    var future: Future(Result) = undefined;
    future.any_future = try io.vtable.concurrent(
        io.userdata,
        @sizeOf(Result),
        .of(Result),
        @ptrCast(&args),
        .of(Args),
        TypeErased.start,
    );
    return future;
}
2 Likes