authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-02-28 10:01:55+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-02-28 14:03:19+01:00
log566adc2510859eaa30eb7c318260c98e712daccf
tree963d59321381ff91148c356ba761dcb5c246cf2f
parente65b6d99ac38686228bf5b5b9c1121382e05da4b

std: Swap arguments in Thread.spawn

Beside the new order being consistent with the ThreadPool API and making more sense, this shuffling allows to write the context argument type in terms of the startFn arguments, reducing the use of anytype (eg. less explicit casts when using comptime_int parameters, yay). Sorry for the breakage. Closes #8082

13 files changed, 49 insertions(+), 35 deletions(-)

lib/std/Thread.zig+20-6
......@@ -165,18 +165,32 @@ pub const SpawnError = error{
165165 Unexpected,
166166};
167167
168/// caller must call wait on the returned thread
169/// fn startFn(@TypeOf(context)) T
170/// where T is u8, noreturn, void, or !void
171/// caller must call wait on the returned thread
172pub fn spawn(context: anytype, comptime startFn: anytype) SpawnError!*Thread {
168// Given `T`, the type of the thread startFn, extract the expected type for the
169// context parameter.
170fn SpawnContextType(comptime T: type) type {
171 const TI = @typeInfo(T);
172 if (TI != .Fn)
173 @compileError("expected function type, found " ++ @typeName(T));
174
175 if (TI.Fn.args.len != 1)
176 @compileError("expected function with single argument, found " ++ @typeName(T));
177
178 return TI.Fn.args[0].arg_type orelse
179 @compileError("cannot use a generic function as thread startFn");
180}
181
182/// Spawns a new thread executing startFn, returning an handle for it.
183/// Caller must call wait on the returned thread.
184/// The `startFn` function must take a single argument of type T and return a
185/// value of type u8, noreturn, void or !void.
186/// The `context` parameter is of type T and is passed to the spawned thread.
187pub fn spawn(comptime startFn: anytype, context: SpawnContextType(@TypeOf(startFn))) SpawnError!*Thread {
173188 if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode");
174189 // TODO compile-time call graph analysis to determine stack upper bound
175190 // https://github.com/ziglang/zig/issues/157
176191 const default_stack_size = 16 * 1024 * 1024;
177192
178193 const Context = @TypeOf(context);
179 comptime assert(@typeInfo(@TypeOf(startFn)).Fn.args[0].arg_type.? == Context);
180194
181195 if (std.Target.current.os.tag == .windows) {
182196 const WinThread = struct {
lib/std/Thread/AutoResetEvent.zig+2-2
......@@ -220,8 +220,8 @@ test "basic usage" {
220220 };
221221
222222 var context = Context{};
223 const send_thread = try std.Thread.spawn(&context, Context.sender);
224 const recv_thread = try std.Thread.spawn(&context, Context.receiver);
223 const send_thread = try std.Thread.spawn(Context.sender, &context);
224 const recv_thread = try std.Thread.spawn(Context.receiver, &context);
225225
226226 send_thread.wait();
227227 recv_thread.wait();
lib/std/Thread/Mutex.zig+1-1
......@@ -299,7 +299,7 @@ test "basic usage" {
299299 const thread_count = 10;
300300 var threads: [thread_count]*std.Thread = undefined;
301301 for (threads) |*t| {
302 t.* = try std.Thread.spawn(&context, worker);
302 t.* = try std.Thread.spawn(worker, &context);
303303 }
304304 for (threads) |t|
305305 t.wait();
lib/std/Thread/ResetEvent.zig+2-2
......@@ -281,7 +281,7 @@ test "basic usage" {
281281 var context: Context = undefined;
282282 try context.init();
283283 defer context.deinit();
284 const receiver = try std.Thread.spawn(&context, Context.receiver);
284 const receiver = try std.Thread.spawn(Context.receiver, &context);
285285 defer receiver.wait();
286286 context.sender();
287287
......@@ -290,7 +290,7 @@ test "basic usage" {
290290 // https://github.com/ziglang/zig/issues/7009
291291 var timed = Context.init();
292292 defer timed.deinit();
293 const sleeper = try std.Thread.spawn(&timed, Context.sleeper);
293 const sleeper = try std.Thread.spawn(Context.sleeper, &timed);
294294 defer sleeper.wait();
295295 try timed.timedWaiter();
296296 }
lib/std/Thread/StaticResetEvent.zig+2-2
......@@ -379,7 +379,7 @@ test "basic usage" {
379379 };
380380
381381 var context = Context{};
382 const receiver = try std.Thread.spawn(&context, Context.receiver);
382 const receiver = try std.Thread.spawn(Context.receiver, &context);
383383 defer receiver.wait();
384384 context.sender();
385385
......@@ -388,7 +388,7 @@ test "basic usage" {
388388 // https://github.com/ziglang/zig/issues/7009
389389 var timed = Context.init();
390390 defer timed.deinit();
391 const sleeper = try std.Thread.spawn(&timed, Context.sleeper);
391 const sleeper = try std.Thread.spawn(Context.sleeper, &timed);
392392 defer sleeper.wait();
393393 try timed.timedWaiter();
394394 }
lib/std/atomic/queue.zig+2-2
......@@ -216,11 +216,11 @@ test "std.atomic.Queue" {
216216
217217 var putters: [put_thread_count]*std.Thread = undefined;
218218 for (putters) |*t| {
219 t.* = try std.Thread.spawn(&context, startPuts);
219 t.* = try std.Thread.spawn(startPuts, &context);
220220 }
221221 var getters: [put_thread_count]*std.Thread = undefined;
222222 for (getters) |*t| {
223 t.* = try std.Thread.spawn(&context, startGets);
223 t.* = try std.Thread.spawn(startGets, &context);
224224 }
225225
226226 for (putters) |t|
lib/std/atomic/stack.zig+2-2
......@@ -123,11 +123,11 @@ test "std.atomic.stack" {
123123 } else {
124124 var putters: [put_thread_count]*std.Thread = undefined;
125125 for (putters) |*t| {
126 t.* = try std.Thread.spawn(&context, startPuts);
126 t.* = try std.Thread.spawn(startPuts, &context);
127127 }
128128 var getters: [put_thread_count]*std.Thread = undefined;
129129 for (getters) |*t| {
130 t.* = try std.Thread.spawn(&context, startGets);
130 t.* = try std.Thread.spawn(startGets, &context);
131131 }
132132
133133 for (putters) |t|
lib/std/event/loop.zig+5-5
......@@ -185,7 +185,7 @@ pub const Loop = struct {
185185 errdefer self.deinitOsData();
186186
187187 if (!builtin.single_threaded) {
188 self.fs_thread = try Thread.spawn(self, posixFsRun);
188 self.fs_thread = try Thread.spawn(posixFsRun, self);
189189 }
190190 errdefer if (!builtin.single_threaded) {
191191 self.posixFsRequest(&self.fs_end_request);
......@@ -264,7 +264,7 @@ pub const Loop = struct {
264264 }
265265 }
266266 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
267 self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
267 self.extra_threads[extra_thread_index] = try Thread.spawn(workerRun, self);
268268 }
269269 },
270270 .macos, .freebsd, .netbsd, .dragonfly, .openbsd => {
......@@ -329,7 +329,7 @@ pub const Loop = struct {
329329 }
330330 }
331331 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
332 self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
332 self.extra_threads[extra_thread_index] = try Thread.spawn(workerRun, self);
333333 }
334334 },
335335 .windows => {
......@@ -378,7 +378,7 @@ pub const Loop = struct {
378378 }
379379 }
380380 while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) {
381 self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun);
381 self.extra_threads[extra_thread_index] = try Thread.spawn(workerRun, self);
382382 }
383383 },
384384 else => {},
......@@ -798,7 +798,7 @@ pub const Loop = struct {
798798 .event = std.Thread.AutoResetEvent{},
799799 .is_running = true,
800800 // Must be last so that it can read the other state, such as `is_running`.
801 .thread = try std.Thread.spawn(self, DelayQueue.run),
801 .thread = try std.Thread.spawn(DelayQueue.run, self),
802802 };
803803 }
804804
lib/std/fs/test.zig+1-1
......@@ -762,7 +762,7 @@ test "open file with exclusive lock twice, make sure it waits" {
762762 try evt.init();
763763 defer evt.deinit();
764764
765 const t = try std.Thread.spawn(S.C{ .dir = &tmp.dir, .evt = &evt }, S.checkFn);
765 const t = try std.Thread.spawn(S.checkFn, S.C{ .dir = &tmp.dir, .evt = &evt });
766766 defer t.wait();
767767
768768 const SLEEP_TIMEOUT_NS = 10 * std.time.ns_per_ms;
lib/std/net/test.zig+2-2
......@@ -161,7 +161,7 @@ test "listen on a port, send bytes, receive bytes" {
161161 }
162162 };
163163
164 const t = try std.Thread.spawn(server.listen_address, S.clientFn);
164 const t = try std.Thread.spawn(S.clientFn, server.listen_address);
165165 defer t.wait();
166166
167167 var client = try server.accept();
......@@ -285,7 +285,7 @@ test "listen on a unix socket, send bytes, receive bytes" {
285285 }
286286 };
287287
288 const t = try std.Thread.spawn({}, S.clientFn);
288 const t = try std.Thread.spawn(S.clientFn, {});
289289 defer t.wait();
290290
291291 var client = try server.accept();
lib/std/once.zig+2-2
......@@ -59,11 +59,11 @@ test "Once executes its function just once" {
5959 defer for (threads) |handle| handle.wait();
6060
6161 for (threads) |*handle| {
62 handle.* = try std.Thread.spawn(@as(u8, 0), struct {
62 handle.* = try std.Thread.spawn(struct {
6363 fn thread_fn(x: u8) void {
6464 global_once.call();
6565 }
66 }.thread_fn);
66 }.thread_fn, 0);
6767 }
6868 }
6969
lib/std/os/test.zig+7-7
......@@ -317,7 +317,7 @@ test "std.Thread.getCurrentId" {
317317 if (builtin.single_threaded) return error.SkipZigTest;
318318
319319 var thread_current_id: Thread.Id = undefined;
320 const thread = try Thread.spawn(&thread_current_id, testThreadIdFn);
320 const thread = try Thread.spawn(testThreadIdFn, &thread_current_id);
321321 const thread_id = thread.handle();
322322 thread.wait();
323323 if (Thread.use_pthreads) {
......@@ -336,10 +336,10 @@ test "spawn threads" {
336336
337337 var shared_ctx: i32 = 1;
338338
339 const thread1 = try Thread.spawn({}, start1);
340 const thread2 = try Thread.spawn(&shared_ctx, start2);
341 const thread3 = try Thread.spawn(&shared_ctx, start2);
342 const thread4 = try Thread.spawn(&shared_ctx, start2);
339 const thread1 = try Thread.spawn(start1, {});
340 const thread2 = try Thread.spawn(start2, &shared_ctx);
341 const thread3 = try Thread.spawn(start2, &shared_ctx);
342 const thread4 = try Thread.spawn(start2, &shared_ctx);
343343
344344 thread1.wait();
345345 thread2.wait();
......@@ -367,8 +367,8 @@ test "cpu count" {
367367
368368test "thread local storage" {
369369 if (builtin.single_threaded) return error.SkipZigTest;
370 const thread1 = try Thread.spawn({}, testTls);
371 const thread2 = try Thread.spawn({}, testTls);
370 const thread1 = try Thread.spawn(testTls, {});
371 const thread2 = try Thread.spawn(testTls, {});
372372 testTls({});
373373 thread1.wait();
374374 thread2.wait();
src/ThreadPool.zig+1-1
......@@ -74,7 +74,7 @@ pub fn init(self: *ThreadPool, allocator: *std.mem.Allocator) !void {
7474 try worker.idle_node.data.init();
7575 errdefer worker.idle_node.data.deinit();
7676
77 worker.thread = try std.Thread.spawn(worker, Worker.run);
77 worker.thread = try std.Thread.spawn(Worker.run, worker);
7878 }
7979}
8080