aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-02-28 20:42:34 -0800
committerGitHub <noreply@github.com>2021-02-28 20:42:34 -0800
commit9550db33cbb7dadd555842ef6d7214660e2b00d6 (patch)
treeffcf41a01dc8a55f06f5a630ed174550be33dad3 /lib/std
parenta5a3ad4f956bae1ca0e5a49de2e9ac7145170039 (diff)
parentd3d3e55fae2299d1ff594c77da2f1f41f44ab525 (diff)
downloadzig-9550db33cbb7dadd555842ef6d7214660e2b00d6.tar.gz
zig-9550db33cbb7dadd555842ef6d7214660e2b00d6.zip
Merge pull request #8097 from LemonBoy/thread-spawn-order
std: Swap arguments in Thread.spawn
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/Thread.zig26
-rw-r--r--lib/std/Thread/AutoResetEvent.zig4
-rw-r--r--lib/std/Thread/Mutex.zig2
-rw-r--r--lib/std/Thread/ResetEvent.zig4
-rw-r--r--lib/std/Thread/StaticResetEvent.zig4
-rw-r--r--lib/std/atomic/queue.zig4
-rw-r--r--lib/std/atomic/stack.zig4
-rw-r--r--lib/std/event/loop.zig10
-rw-r--r--lib/std/fs/test.zig2
-rw-r--r--lib/std/net/test.zig4
-rw-r--r--lib/std/once.zig4
-rw-r--r--lib/std/os/test.zig14
12 files changed, 48 insertions, 34 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();