From 26ee319498a747b28d974f0a7c308292b2a38826 Mon Sep 17 00:00:00 2001 From: mrtowers Date: Tue, 10 Jun 2025 21:59:20 +0000 Subject: [PATCH 1/3] added callFn to limit startFn return types --- lib/std/Thread/Pool.zig | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/std/Thread/Pool.zig b/lib/std/Thread/Pool.zig index e836665d70cf..435be25fe717 100644 --- a/lib/std/Thread/Pool.zig +++ b/lib/std/Thread/Pool.zig @@ -115,7 +115,7 @@ pub fn spawnWg(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args fn runFn(runnable: *Runnable, _: ?usize) void { const closure: *@This() = @alignCast(@fieldParentPtr("runnable", runnable)); - @call(.auto, func, closure.arguments); + callFn(func, closure.arguments); closure.wait_group.finish(); // The thread pool's allocator is protected by the mutex. @@ -132,7 +132,7 @@ pub fn spawnWg(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args const closure = pool.allocator.create(Closure) catch { pool.mutex.unlock(); - @call(.auto, func, args); + callFn(func, args); wait_group.finish(); return; }; @@ -213,9 +213,41 @@ pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, ar pool.cond.signal(); } +/// Used by spawn functions to limit 'f' return type to void, noreturn or error union with void or noreturn. +fn callFn(f: anytype, args: anytype) void { + const bad_fn_return = "expected return type of startFn to be 'noreturn', '!noreturn', 'void', or '!void'"; + + switch (@typeInfo(@typeInfo(@TypeOf(f)).@"fn".return_type.?)) { + .void, .noreturn => { + @call(.auto, f, args); + }, + + .error_union => |info| { + switch (info.payload) { + void, noreturn => { + @call(.auto, f, args) catch |err| { + std.debug.print("error: {s}\n", .{@errorName(err)}); + if (@errorReturnTrace()) |trace| { + std.debug.dumpStackTrace(trace.*); + } + }; + }, + + else => { + @compileError(bad_fn_return); + }, + } + }, + + else => { + @compileError(bad_fn_return); + }, + } +} + pub fn spawn(pool: *Pool, comptime func: anytype, args: anytype) !void { if (builtin.single_threaded) { - @call(.auto, func, args); + callFn(func, args); return; } @@ -227,7 +259,7 @@ pub fn spawn(pool: *Pool, comptime func: anytype, args: anytype) !void { fn runFn(runnable: *Runnable, _: ?usize) void { const closure: *@This() = @alignCast(@fieldParentPtr("runnable", runnable)); - @call(.auto, func, closure.arguments); + callFn(func, closure.arguments); // The thread pool's allocator is protected by the mutex. const mutex = &closure.pool.mutex; From 8ee7a2e28297c354c54000c746a5caf9e046eb0c Mon Sep 17 00:00:00 2001 From: mrtowers Date: Tue, 10 Jun 2025 22:26:44 +0000 Subject: [PATCH 2/3] added callFn to spawnWgId --- lib/std/Thread/Pool.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/std/Thread/Pool.zig b/lib/std/Thread/Pool.zig index 435be25fe717..dd5792d8d746 100644 --- a/lib/std/Thread/Pool.zig +++ b/lib/std/Thread/Pool.zig @@ -163,7 +163,7 @@ pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, ar wait_group.start(); if (builtin.single_threaded) { - @call(.auto, func, .{0} ++ args); + callFn(func, .{0} ++ args); wait_group.finish(); return; } @@ -177,7 +177,7 @@ pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, ar fn runFn(runnable: *Runnable, id: ?usize) void { const closure: *@This() = @alignCast(@fieldParentPtr("runnable", runnable)); - @call(.auto, func, .{id.?} ++ closure.arguments); + callFn(func, .{id.?} ++ closure.arguments); closure.wait_group.finish(); // The thread pool's allocator is protected by the mutex. @@ -195,7 +195,7 @@ pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, ar const closure = pool.allocator.create(Closure) catch { const id: ?usize = pool.ids.getIndex(std.Thread.getCurrentId()); pool.mutex.unlock(); - @call(.auto, func, .{id.?} ++ args); + callFn(func, .{id.?} ++ args); wait_group.finish(); return; }; From 48248b1ddd410ba85195a7a4e459e9e51a192906 Mon Sep 17 00:00:00 2001 From: mrtowers Date: Wed, 11 Jun 2025 06:54:10 +0200 Subject: [PATCH 3/3] std.Thread.Pool: spawnWg callFn in single_threaded --- lib/std/Thread/Pool.zig | 66 ++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/lib/std/Thread/Pool.zig b/lib/std/Thread/Pool.zig index dd5792d8d746..63d570137770 100644 --- a/lib/std/Thread/Pool.zig +++ b/lib/std/Thread/Pool.zig @@ -92,6 +92,38 @@ fn join(pool: *Pool, spawned: usize) void { pool.allocator.free(pool.threads); } +/// Used by spawn functions to limit 'f' return type to void, noreturn or error union with void or noreturn. +fn callFn(f: anytype, args: anytype) void { + const bad_fn_return = "expected return type of startFn to be 'noreturn', '!noreturn', 'void', or '!void'"; + + switch (@typeInfo(@typeInfo(@TypeOf(f)).@"fn".return_type.?)) { + .void, .noreturn => { + @call(.auto, f, args); + }, + + .error_union => |info| { + switch (info.payload) { + void, noreturn => { + @call(.auto, f, args) catch |err| { + std.debug.print("error: {s}\n", .{@errorName(err)}); + if (@errorReturnTrace()) |trace| { + std.debug.dumpStackTrace(trace.*); + } + }; + }, + + else => { + @compileError(bad_fn_return); + }, + } + }, + + else => { + @compileError(bad_fn_return); + }, + } +} + /// Runs `func` in the thread pool, calling `WaitGroup.start` beforehand, and /// `WaitGroup.finish` after it returns. /// @@ -101,7 +133,7 @@ pub fn spawnWg(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args wait_group.start(); if (builtin.single_threaded) { - @call(.auto, func, args); + callFn(func, args); wait_group.finish(); return; } @@ -213,38 +245,6 @@ pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, ar pool.cond.signal(); } -/// Used by spawn functions to limit 'f' return type to void, noreturn or error union with void or noreturn. -fn callFn(f: anytype, args: anytype) void { - const bad_fn_return = "expected return type of startFn to be 'noreturn', '!noreturn', 'void', or '!void'"; - - switch (@typeInfo(@typeInfo(@TypeOf(f)).@"fn".return_type.?)) { - .void, .noreturn => { - @call(.auto, f, args); - }, - - .error_union => |info| { - switch (info.payload) { - void, noreturn => { - @call(.auto, f, args) catch |err| { - std.debug.print("error: {s}\n", .{@errorName(err)}); - if (@errorReturnTrace()) |trace| { - std.debug.dumpStackTrace(trace.*); - } - }; - }, - - else => { - @compileError(bad_fn_return); - }, - } - }, - - else => { - @compileError(bad_fn_return); - }, - } -} - pub fn spawn(pool: *Pool, comptime func: anytype, args: anytype) !void { if (builtin.single_threaded) { callFn(func, args);