Calls function with args, such that the return value of the function is
not guaranteed to be available until await is called, allowing the caller
to progress while waiting for any Io operations.
This has stronger guarantee than async, placing restrictions on what kind
of Io implementations are supported. By calling async instead, one
allows, for example, stackful single-threaded blocking I/O.
pub fn concurrent(
io: Io,
function: anytype,
args: std.meta.ArgsTuple(@TypeOf(function)),
) ConcurrentError!Future(@typeInfo(@TypeOf(function)).@"fn".return_type.?)
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;
}