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