diff options
| author | LemonBoy <thatlemon@gmail.com> | 2021-02-28 10:01:55 +0100 |
|---|---|---|
| committer | LemonBoy <thatlemon@gmail.com> | 2021-02-28 14:03:19 +0100 |
| commit | 566adc2510859eaa30eb7c318260c98e712daccf (patch) | |
| tree | 963d59321381ff91148c356ba761dcb5c246cf2f | |
| parent | e65b6d99ac38686228bf5b5b9c1121382e05da4b (diff) | |
| download | zig-566adc2510859eaa30eb7c318260c98e712daccf.tar.gz zig-566adc2510859eaa30eb7c318260c98e712daccf.zip | |
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
| -rw-r--r-- | lib/std/Thread.zig | 26 | ||||
| -rw-r--r-- | lib/std/Thread/AutoResetEvent.zig | 4 | ||||
| -rw-r--r-- | lib/std/Thread/Mutex.zig | 2 | ||||
| -rw-r--r-- | lib/std/Thread/ResetEvent.zig | 4 | ||||
| -rw-r--r-- | lib/std/Thread/StaticResetEvent.zig | 4 | ||||
| -rw-r--r-- | lib/std/atomic/queue.zig | 4 | ||||
| -rw-r--r-- | lib/std/atomic/stack.zig | 4 | ||||
| -rw-r--r-- | lib/std/event/loop.zig | 10 | ||||
| -rw-r--r-- | lib/std/fs/test.zig | 2 | ||||
| -rw-r--r-- | lib/std/net/test.zig | 4 | ||||
| -rw-r--r-- | lib/std/once.zig | 4 | ||||
| -rw-r--r-- | lib/std/os/test.zig | 14 | ||||
| -rw-r--r-- | src/ThreadPool.zig | 2 |
13 files changed, 49 insertions, 35 deletions
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 77277bd154..b9a69d151f 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -165,18 +165,32 @@ pub const SpawnError = error{ Unexpected, }; -/// caller must call wait on the returned thread -/// fn startFn(@TypeOf(context)) T -/// where T is u8, noreturn, void, or !void -/// caller must call wait on the returned thread -pub fn spawn(context: anytype, comptime startFn: anytype) SpawnError!*Thread { +// Given `T`, the type of the thread startFn, extract the expected type for the +// context parameter. +fn SpawnContextType(comptime T: type) type { + const TI = @typeInfo(T); + if (TI != .Fn) + @compileError("expected function type, found " ++ @typeName(T)); + + if (TI.Fn.args.len != 1) + @compileError("expected function with single argument, found " ++ @typeName(T)); + + return TI.Fn.args[0].arg_type orelse + @compileError("cannot use a generic function as thread startFn"); +} + +/// Spawns a new thread executing startFn, returning an handle for it. +/// Caller must call wait on the returned thread. +/// The `startFn` function must take a single argument of type T and return a +/// value of type u8, noreturn, void or !void. +/// The `context` parameter is of type T and is passed to the spawned thread. +pub fn spawn(comptime startFn: anytype, context: SpawnContextType(@TypeOf(startFn))) SpawnError!*Thread { if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode"); // TODO compile-time call graph analysis to determine stack upper bound // https://github.com/ziglang/zig/issues/157 const default_stack_size = 16 * 1024 * 1024; const Context = @TypeOf(context); - comptime assert(@typeInfo(@TypeOf(startFn)).Fn.args[0].arg_type.? == Context); if (std.Target.current.os.tag == .windows) { const WinThread = struct { diff --git a/lib/std/Thread/AutoResetEvent.zig b/lib/std/Thread/AutoResetEvent.zig index 8b8b5658bf..0726dc794a 100644 --- a/lib/std/Thread/AutoResetEvent.zig +++ b/lib/std/Thread/AutoResetEvent.zig @@ -220,8 +220,8 @@ test "basic usage" { }; var context = Context{}; - const send_thread = try std.Thread.spawn(&context, Context.sender); - const recv_thread = try std.Thread.spawn(&context, Context.receiver); + const send_thread = try std.Thread.spawn(Context.sender, &context); + const recv_thread = try std.Thread.spawn(Context.receiver, &context); send_thread.wait(); recv_thread.wait(); diff --git a/lib/std/Thread/Mutex.zig b/lib/std/Thread/Mutex.zig index 94711bcda0..e7d11954bf 100644 --- a/lib/std/Thread/Mutex.zig +++ b/lib/std/Thread/Mutex.zig @@ -299,7 +299,7 @@ test "basic usage" { const thread_count = 10; var threads: [thread_count]*std.Thread = undefined; for (threads) |*t| { - t.* = try std.Thread.spawn(&context, worker); + t.* = try std.Thread.spawn(worker, &context); } for (threads) |t| t.wait(); diff --git a/lib/std/Thread/ResetEvent.zig b/lib/std/Thread/ResetEvent.zig index 622f9be98e..439fb0db40 100644 --- a/lib/std/Thread/ResetEvent.zig +++ b/lib/std/Thread/ResetEvent.zig @@ -281,7 +281,7 @@ test "basic usage" { var context: Context = undefined; try context.init(); defer context.deinit(); - const receiver = try std.Thread.spawn(&context, Context.receiver); + const receiver = try std.Thread.spawn(Context.receiver, &context); defer receiver.wait(); context.sender(); @@ -290,7 +290,7 @@ test "basic usage" { // https://github.com/ziglang/zig/issues/7009 var timed = Context.init(); defer timed.deinit(); - const sleeper = try std.Thread.spawn(&timed, Context.sleeper); + const sleeper = try std.Thread.spawn(Context.sleeper, &timed); defer sleeper.wait(); try timed.timedWaiter(); } diff --git a/lib/std/Thread/StaticResetEvent.zig b/lib/std/Thread/StaticResetEvent.zig index 6d90d7cf9a..07a8e50c16 100644 --- a/lib/std/Thread/StaticResetEvent.zig +++ b/lib/std/Thread/StaticResetEvent.zig @@ -379,7 +379,7 @@ test "basic usage" { }; var context = Context{}; - const receiver = try std.Thread.spawn(&context, Context.receiver); + const receiver = try std.Thread.spawn(Context.receiver, &context); defer receiver.wait(); context.sender(); @@ -388,7 +388,7 @@ test "basic usage" { // https://github.com/ziglang/zig/issues/7009 var timed = Context.init(); defer timed.deinit(); - const sleeper = try std.Thread.spawn(&timed, Context.sleeper); + const sleeper = try std.Thread.spawn(Context.sleeper, &timed); defer sleeper.wait(); try timed.timedWaiter(); } diff --git a/lib/std/atomic/queue.zig b/lib/std/atomic/queue.zig index f5f63944ab..4e427a1669 100644 --- a/lib/std/atomic/queue.zig +++ b/lib/std/atomic/queue.zig @@ -216,11 +216,11 @@ test "std.atomic.Queue" { var putters: [put_thread_count]*std.Thread = undefined; for (putters) |*t| { - t.* = try std.Thread.spawn(&context, startPuts); + t.* = try std.Thread.spawn(startPuts, &context); } var getters: [put_thread_count]*std.Thread = undefined; for (getters) |*t| { - t.* = try std.Thread.spawn(&context, startGets); + t.* = try std.Thread.spawn(startGets, &context); } for (putters) |t| diff --git a/lib/std/atomic/stack.zig b/lib/std/atomic/stack.zig index d55a8f81a3..4096c27354 100644 --- a/lib/std/atomic/stack.zig +++ b/lib/std/atomic/stack.zig @@ -123,11 +123,11 @@ test "std.atomic.stack" { } else { var putters: [put_thread_count]*std.Thread = undefined; for (putters) |*t| { - t.* = try std.Thread.spawn(&context, startPuts); + t.* = try std.Thread.spawn(startPuts, &context); } var getters: [put_thread_count]*std.Thread = undefined; for (getters) |*t| { - t.* = try std.Thread.spawn(&context, startGets); + t.* = try std.Thread.spawn(startGets, &context); } for (putters) |t| diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 912f99e961..878cea4aa6 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -185,7 +185,7 @@ pub const Loop = struct { errdefer self.deinitOsData(); if (!builtin.single_threaded) { - self.fs_thread = try Thread.spawn(self, posixFsRun); + self.fs_thread = try Thread.spawn(posixFsRun, self); } errdefer if (!builtin.single_threaded) { self.posixFsRequest(&self.fs_end_request); @@ -264,7 +264,7 @@ pub const Loop = struct { } } while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) { - self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun); + self.extra_threads[extra_thread_index] = try Thread.spawn(workerRun, self); } }, .macos, .freebsd, .netbsd, .dragonfly, .openbsd => { @@ -329,7 +329,7 @@ pub const Loop = struct { } } while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) { - self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun); + self.extra_threads[extra_thread_index] = try Thread.spawn(workerRun, self); } }, .windows => { @@ -378,7 +378,7 @@ pub const Loop = struct { } } while (extra_thread_index < extra_thread_count) : (extra_thread_index += 1) { - self.extra_threads[extra_thread_index] = try Thread.spawn(self, workerRun); + self.extra_threads[extra_thread_index] = try Thread.spawn(workerRun, self); } }, else => {}, @@ -798,7 +798,7 @@ pub const Loop = struct { .event = std.Thread.AutoResetEvent{}, .is_running = true, // Must be last so that it can read the other state, such as `is_running`. - .thread = try std.Thread.spawn(self, DelayQueue.run), + .thread = try std.Thread.spawn(DelayQueue.run, self), }; } diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index e9f28a0b60..0e2d296bb7 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -762,7 +762,7 @@ test "open file with exclusive lock twice, make sure it waits" { try evt.init(); defer evt.deinit(); - const t = try std.Thread.spawn(S.C{ .dir = &tmp.dir, .evt = &evt }, S.checkFn); + const t = try std.Thread.spawn(S.checkFn, S.C{ .dir = &tmp.dir, .evt = &evt }); defer t.wait(); const SLEEP_TIMEOUT_NS = 10 * std.time.ns_per_ms; diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig index 10a9c4e18b..4470d17aeb 100644 --- a/lib/std/net/test.zig +++ b/lib/std/net/test.zig @@ -161,7 +161,7 @@ test "listen on a port, send bytes, receive bytes" { } }; - const t = try std.Thread.spawn(server.listen_address, S.clientFn); + const t = try std.Thread.spawn(S.clientFn, server.listen_address); defer t.wait(); var client = try server.accept(); @@ -285,7 +285,7 @@ test "listen on a unix socket, send bytes, receive bytes" { } }; - const t = try std.Thread.spawn({}, S.clientFn); + const t = try std.Thread.spawn(S.clientFn, {}); defer t.wait(); var client = try server.accept(); diff --git a/lib/std/once.zig b/lib/std/once.zig index efa99060d3..79d273b86a 100644 --- a/lib/std/once.zig +++ b/lib/std/once.zig @@ -59,11 +59,11 @@ test "Once executes its function just once" { defer for (threads) |handle| handle.wait(); for (threads) |*handle| { - handle.* = try std.Thread.spawn(@as(u8, 0), struct { + handle.* = try std.Thread.spawn(struct { fn thread_fn(x: u8) void { global_once.call(); } - }.thread_fn); + }.thread_fn, 0); } } diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index f08d4d58fa..c8cef38d5d 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -317,7 +317,7 @@ test "std.Thread.getCurrentId" { if (builtin.single_threaded) return error.SkipZigTest; var thread_current_id: Thread.Id = undefined; - const thread = try Thread.spawn(&thread_current_id, testThreadIdFn); + const thread = try Thread.spawn(testThreadIdFn, &thread_current_id); const thread_id = thread.handle(); thread.wait(); if (Thread.use_pthreads) { @@ -336,10 +336,10 @@ test "spawn threads" { var shared_ctx: i32 = 1; - const thread1 = try Thread.spawn({}, start1); - const thread2 = try Thread.spawn(&shared_ctx, start2); - const thread3 = try Thread.spawn(&shared_ctx, start2); - const thread4 = try Thread.spawn(&shared_ctx, start2); + const thread1 = try Thread.spawn(start1, {}); + const thread2 = try Thread.spawn(start2, &shared_ctx); + const thread3 = try Thread.spawn(start2, &shared_ctx); + const thread4 = try Thread.spawn(start2, &shared_ctx); thread1.wait(); thread2.wait(); @@ -367,8 +367,8 @@ test "cpu count" { test "thread local storage" { if (builtin.single_threaded) return error.SkipZigTest; - const thread1 = try Thread.spawn({}, testTls); - const thread2 = try Thread.spawn({}, testTls); + const thread1 = try Thread.spawn(testTls, {}); + const thread2 = try Thread.spawn(testTls, {}); testTls({}); thread1.wait(); thread2.wait(); diff --git a/src/ThreadPool.zig b/src/ThreadPool.zig index ec580210e9..e66742b49e 100644 --- a/src/ThreadPool.zig +++ b/src/ThreadPool.zig @@ -74,7 +74,7 @@ pub fn init(self: *ThreadPool, allocator: *std.mem.Allocator) !void { try worker.idle_node.data.init(); errdefer worker.idle_node.data.deinit(); - worker.thread = try std.Thread.spawn(worker, Worker.run); + worker.thread = try std.Thread.spawn(Worker.run, worker); } } |
