add runDetached to event loop

Signed-off-by: Loris Cro <kappaloris@gmail.com>
This commit is contained in:
Loris Cro 2020-09-29 14:50:46 +02:00
parent a0c0f9ead5
commit 16f0419700

View File

@ -647,6 +647,29 @@ pub const Loop = struct {
}
}
/// Runs the provided function asynchonously, similarly to Go's "go" operator.
/// `func` must return void and it can be an async function.
fn runDetached(self: *Loop, alloc: *mem.Allocator, comptime func: anytype, args: anytype) error{OutOfMemory}!void {
if (!std.io.is_async) @compileError("Can't use runDetached in non-async mode!");
if (@TypeOf(@call(.{}, func, args)) != void) {
@compileError("`func` must not have a return value");
}
const Wrapper = struct {
const Args = @TypeOf(args);
fn run(func_args: Args, loop: *Loop, allocator: *mem.Allocator) void {
loop.yield();
const result = @call(.{}, func, func_args);
suspend {
allocator.destroy(@frame());
}
}
};
var run_frame = try alloc.create(@Frame(Wrapper.run));
run_frame.* = async Wrapper.run(args, self, alloc);
}
/// Yielding lets the event loop run, starting any unstarted async operations.
/// Note that async operations automatically start when a function yields for any other reason,
/// for example, when async I/O is performed. This function is intended to be used only when
@ -1493,3 +1516,33 @@ fn testEventLoop2(h: anyframe->i32, did_it: *bool) void {
testing.expect(value == 1234);
did_it.* = true;
}
var testRunDetachedData: usize = 0;
test "std.event.Loop - runDetached" {
// https://github.com/ziglang/zig/issues/1908
if (builtin.single_threaded) return error.SkipZigTest;
if (!std.io.is_async) return error.SkipZigTest;
if (true) {
// https://github.com/ziglang/zig/issues/4922
return error.SkipZigTest;
}
var loop: Loop = undefined;
try loop.initMultiThreaded();
defer loop.deinit();
// Schedule the execution, won't actually start until we start the
// event loop.
try loop.runDetached(std.testing.allocator, testRunDetached, .{});
// Now we can start the event loop. The function will return only
// after all tasks have been completed, allowing us to synchonize
// with the previous runDetached.
loop.run();
testing.expect(testRunDetachedData == 1);
}
fn testRunDetached() void {
testRunDetachedData += 1;
}