authorgravatar for alex_naskos@hotmail.comAlexandros Naskos <alex_naskos@hotmail.com> 2020-10-01 15:57:02+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-10-01 15:57:02+03:00
logbeda6f2299d918cb5ed3444f18e985dc7de448b0
treee525fdf2e0abc09e7d88f88532515368ecc2a966
parentb358c281718a2f6437612fb73590a4992242cf52
parent16f041970007d997d67ee2e15f0eba1053204808
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6455 from kristoff-it/event-loop-go

add runDetached to event loop

1 files changed, 53 insertions(+), 0 deletions(-)

lib/std/event/loop.zig+53
...@@ -647,6 +647,29 @@ pub const Loop = struct {...@@ -647,6 +647,29 @@ pub const Loop = struct {
647 }647 }
648 }648 }
649649
650 /// Runs the provided function asynchonously, similarly to Go's "go" operator.
651 /// `func` must return void and it can be an async function.
652 fn runDetached(self: *Loop, alloc: *mem.Allocator, comptime func: anytype, args: anytype) error{OutOfMemory}!void {
653 if (!std.io.is_async) @compileError("Can't use runDetached in non-async mode!");
654 if (@TypeOf(@call(.{}, func, args)) != void) {
655 @compileError("`func` must not have a return value");
656 }
657
658 const Wrapper = struct {
659 const Args = @TypeOf(args);
660 fn run(func_args: Args, loop: *Loop, allocator: *mem.Allocator) void {
661 loop.yield();
662 const result = @call(.{}, func, func_args);
663 suspend {
664 allocator.destroy(@frame());
665 }
666 }
667 };
668
669 var run_frame = try alloc.create(@Frame(Wrapper.run));
670 run_frame.* = async Wrapper.run(args, self, alloc);
671 }
672
650 /// Yielding lets the event loop run, starting any unstarted async operations.673 /// Yielding lets the event loop run, starting any unstarted async operations.
651 /// Note that async operations automatically start when a function yields for any other reason,674 /// Note that async operations automatically start when a function yields for any other reason,
652 /// for example, when async I/O is performed. This function is intended to be used only when675 /// 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 {...@@ -1493,3 +1516,33 @@ fn testEventLoop2(h: anyframe->i32, did_it: *bool) void {
1493 testing.expect(value == 1234);1516 testing.expect(value == 1234);
1494 did_it.* = true;1517 did_it.* = true;
1495}1518}
1519
1520var testRunDetachedData: usize = 0;
1521test "std.event.Loop - runDetached" {
1522 // https://github.com/ziglang/zig/issues/1908
1523 if (builtin.single_threaded) return error.SkipZigTest;
1524 if (!std.io.is_async) return error.SkipZigTest;
1525 if (true) {
1526 // https://github.com/ziglang/zig/issues/4922
1527 return error.SkipZigTest;
1528 }
1529
1530 var loop: Loop = undefined;
1531 try loop.initMultiThreaded();
1532 defer loop.deinit();
1533
1534 // Schedule the execution, won't actually start until we start the
1535 // event loop.
1536 try loop.runDetached(std.testing.allocator, testRunDetached, .{});
1537
1538 // Now we can start the event loop. The function will return only
1539 // after all tasks have been completed, allowing us to synchonize
1540 // with the previous runDetached.
1541 loop.run();
1542
1543 testing.expect(testRunDetachedData == 1);
1544}
1545
1546fn testRunDetached() void {
1547 testRunDetachedData += 1;
1548}