| ... | @@ -6,6 +6,8 @@ const windows = std.os.windows; | ... | @@ -6,6 +6,8 @@ const windows = std.os.windows; |
| 6 | const c = std.c; | 6 | const c = std.c; |
| 7 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 8 | | 8 | |
| | 9 | const bad_startfn_ret = "expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"; |
| | 10 | |
| 9 | pub const Thread = struct { | 11 | pub const Thread = struct { |
| 10 | data: Data, | 12 | data: Data, |
| 11 | | 13 | |
| ... | @@ -158,15 +160,34 @@ pub const Thread = struct { | ... | @@ -158,15 +160,34 @@ pub const Thread = struct { |
| 158 | }; | 160 | }; |
| 159 | fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD { | 161 | fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD { |
| 160 | const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*; | 162 | const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*; |
| | 163 | |
| 161 | switch (@typeInfo(@TypeOf(startFn).ReturnType)) { | 164 | switch (@typeInfo(@TypeOf(startFn).ReturnType)) { |
| 162 | .Int => { | 165 | .NoReturn => { |
| 163 | return startFn(arg); | 166 | startFn(arg); |
| 164 | }, | 167 | }, |
| 165 | .Void => { | 168 | .Void => { |
| 166 | startFn(arg); | 169 | startFn(arg); |
| 167 | return 0; | 170 | return 0; |
| 168 | }, | 171 | }, |
| 169 | else => @compileError("expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"), | 172 | .Int => |info| { |
| | 173 | if (info.bits != 8) { |
| | 174 | @compileError(bad_startfn_ret); |
| | 175 | } |
| | 176 | return startFn(arg); |
| | 177 | }, |
| | 178 | .ErrorUnion => |info| { |
| | 179 | if (info.payload != void) { |
| | 180 | @compileError(bad_startfn_ret); |
| | 181 | } |
| | 182 | startFn(arg) catch |err| { |
| | 183 | std.debug.warn("error: {}\n", .{@errorName(err)}); |
| | 184 | if (@errorReturnTrace()) |trace| { |
| | 185 | std.debug.dumpStackTrace(trace.*); |
| | 186 | } |
| | 187 | }; |
| | 188 | return 0; |
| | 189 | }, |
| | 190 | else => @compileError(bad_startfn_ret), |
| 170 | } | 191 | } |
| 171 | } | 192 | } |
| 172 | }; | 193 | }; |
| ... | @@ -202,14 +223,32 @@ pub const Thread = struct { | ... | @@ -202,14 +223,32 @@ pub const Thread = struct { |
| 202 | const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*; | 223 | const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*; |
| 203 | | 224 | |
| 204 | switch (@typeInfo(@TypeOf(startFn).ReturnType)) { | 225 | switch (@typeInfo(@TypeOf(startFn).ReturnType)) { |
| 205 | .Int => { | 226 | .NoReturn => { |
| 206 | return startFn(arg); | 227 | startFn(arg); |
| 207 | }, | 228 | }, |
| 208 | .Void => { | 229 | .Void => { |
| 209 | startFn(arg); | 230 | startFn(arg); |
| 210 | return 0; | 231 | return 0; |
| 211 | }, | 232 | }, |
| 212 | else => @compileError("expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"), | 233 | .Int => |info| { |
| | 234 | if (info.bits != 8) { |
| | 235 | @compileError(bad_startfn_ret); |
| | 236 | } |
| | 237 | return startFn(arg); |
| | 238 | }, |
| | 239 | .ErrorUnion => |info| { |
| | 240 | if (info.payload != void) { |
| | 241 | @compileError(bad_startfn_ret); |
| | 242 | } |
| | 243 | startFn(arg) catch |err| { |
| | 244 | std.debug.warn("error: {}\n", .{@errorName(err)}); |
| | 245 | if (@errorReturnTrace()) |trace| { |
| | 246 | std.debug.dumpStackTrace(trace.*); |
| | 247 | } |
| | 248 | }; |
| | 249 | return 0; |
| | 250 | }, |
| | 251 | else => @compileError(bad_startfn_ret), |
| 213 | } | 252 | } |
| 214 | } | 253 | } |
| 215 | fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void { | 254 | fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void { |