| author | |
| committer | |
| log | 9550db33cbb7dadd555842ef6d7214660e2b00d6 |
| tree | ffcf41a01dc8a55f06f5a630ed174550be33dad3 |
| parent | a5a3ad4f956bae1ca0e5a49de2e9ac7145170039 |
| parent | d3d3e55fae2299d1ff594c77da2f1f41f44ab525 |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
std: Swap arguments in Thread.spawn14 files changed, 51 insertions(+), 37 deletions(-)
doc/langref.html.in+2-2| ... | ... | @@ -933,8 +933,8 @@ const assert = std.debug.assert; |
| 933 | 933 | threadlocal var x: i32 = 1234; |
| 934 | 934 | |
| 935 | 935 | test "thread local storage" { |
| 936 | const thread1 = try std.Thread.spawn({}, testTls); | |
| 937 | const thread2 = try std.Thread.spawn({}, testTls); | |
| 936 | const thread1 = try std.Thread.spawn(testTls, {}); | |
| 937 | const thread2 = try std.Thread.spawn(testTls, {}); | |
| 938 | 938 | testTls({}); |
| 939 | 939 | thread1.wait(); |
| 940 | 940 | thread2.wait(); |
lib/std/Thread.zig+20-6| ... | ... | @@ -165,18 +165,32 @@ pub const SpawnError = error{ |
| 165 | 165 | Unexpected, |
| 166 | 166 | }; |
| 167 | 167 | |
| 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 | |
| 172 | pub 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. | |
| 170 | fn 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. | |
| 187 | pub fn spawn(comptime startFn: anytype, context: SpawnContextType(@TypeOf(startFn))) SpawnError!*Thread { | |
| 173 | 188 | if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode"); |
| 174 | 189 | // TODO compile-time call graph analysis to determine stack upper bound |
| 175 | 190 | // https://github.com/ziglang/zig/issues/157 |
| 176 | 191 | const default_stack_size = 16 * 1024 * 1024; |
| 177 | 192 | |
| 178 | 193 | const Context = @TypeOf(context); |
| 179 | comptime assert(@typeInfo(@TypeOf(startFn)).Fn.args[0].arg_type.? == Context); | |
| 180 | 194 | |
| 181 | 195 | if (std.Target.current.os.tag == .windows) { |
| 182 | 196 | const WinThread = struct { |
lib/std/Thread/AutoResetEvent.zig+2-2| ... | ... | @@ -220,8 +220,8 @@ test "basic usage" { |
| 220 | 220 | }; |
| 221 | 221 | |
| 222 | 222 | 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); | |
| 225 | 225 | |
| 226 | 226 | send_thread.wait(); |
| 227 | 227 | recv_thread.wait(); |
lib/std/Thread/Mutex.zig+1-1| ... | ... | @@ -299,7 +299,7 @@ test "basic usage" { |
| 299 | 299 | const thread_count = 10; |
| 300 | 300 | var threads: [thread_count]*std.Thread = undefined; |
| 301 | 301 | for (threads) |*t| { |
| 302 | t.* = try std.Thread.spawn(&context, worker); | |
| 302 | t.* = try std.Thread.spawn(worker, &context); | |
| 303 | 303 | } |
| 304 | 304 | for (threads) |t| |
| 305 | 305 | t.wait(); |
lib/std/Thread/ResetEvent.zig+2-2| ... | ... | @@ -281,7 +281,7 @@ test "basic usage" { |
| 281 | 281 | var context: Context = undefined; |
| 282 | 282 | try context.init(); |
| 283 | 283 | defer context.deinit(); |
| 284 | const receiver = try std.Thread.spawn(&context, Context.receiver); | |
| 284 | const receiver = try std.Thread.spawn(Context.receiver, &context); | |
| 285 | 285 | defer receiver.wait(); |
| 286 | 286 | context.sender(); |
| 287 | 287 | |
| ... | ... | @@ -290,7 +290,7 @@ test "basic usage" { |
| 290 | 290 | // https://github.com/ziglang/zig/issues/7009 |
| 291 | 291 | var timed = Context.init(); |
| 292 | 292 | defer timed.deinit(); |
| 293 | const sleeper = try std.Thread.spawn(&timed, Context.sleeper); | |
| 293 | const sleeper = try std.Thread.spawn(Context.sleeper, &timed); | |
| 294 | 294 | defer sleeper.wait(); |
| 295 | 295 | try timed.timedWaiter(); |
| 296 | 296 | } |
lib/std/Thread/StaticResetEvent.zig+2-2| ... | ... | @@ -379,7 +379,7 @@ test "basic usage" { |
| 379 | 379 | }; |
| 380 | 380 | |
| 381 | 381 | var context = Context{}; |
| 382 | const receiver = try std.Thread.spawn(&context, Context.receiver); | |
| 382 | const receiver = try std.Thread.spawn(Context.receiver, &context); | |
| 383 | 383 | defer receiver.wait(); |
| 384 | 384 | context.sender(); |
| 385 | 385 | |
| ... | ... | @@ -388,7 +388,7 @@ test "basic usage" { |
| 388 | 388 | // https://github.com/ziglang/zig/issues/7009 |
| 389 | 389 | var timed = Context.init(); |
| 390 | 390 | defer timed.deinit(); |
| 391 | const sleeper = try std.Thread.spawn(&timed, Context.sleeper); | |
| 391 | const sleeper = try std.Thread.spawn(Context.sleeper, &timed); | |
| 392 | 392 | defer sleeper.wait(); |
| 393 | 393 | try timed.timedWaiter(); |
| 394 | 394 | } |
lib/std/atomic/queue.zig+2-2| ... | ... | @@ -216,11 +216,11 @@ test "std.atomic.Queue" { |
| 216 | 216 | |
| 217 | 217 | var putters: [put_thread_count]*std.Thread = undefined; |
| 218 | 218 | for (putters) |*t| { |
| 219 | t.* = try std.Thread.spawn(&context, startPuts); | |
| 219 | t.* = try std.Thread.spawn(startPuts, &context); | |
| 220 | 220 | } |
| 221 | 221 | var getters: [put_thread_count]*std.Thread = undefined; |
| 222 | 222 | for (getters) |*t| { |
| 223 | t.* = try std.Thread.spawn(&context, startGets); | |
| 223 | t.* = try std.Thread.spawn(startGets, &context); | |
| 224 | 224 | } |
| 225 | 225 | |
| 226 | 226 | for (putters) |t| |
lib/std/atomic/stack.zig+2-2| ... | ... | @@ -123,11 +123,11 @@ test "std.atomic.stack" { |
| 123 | 123 | } else { |
| 124 | 124 | var putters: [put_thread_count]*std.Thread = undefined; |
| 125 | 125 | for (putters) |*t| { |
| 126 | t.* = try std.Thread.spawn(&context, startPuts); | |
| 126 | t.* = try std.Thread.spawn(startPuts, &context); | |
| 127 | 127 | } |
| 128 | 128 | var getters: [put_thread_count]*std.Thread = undefined; |
| 129 | 129 | for (getters) |*t| { |
| 130 | t.* = try std.Thread.spawn(&context, startGets); | |
| 130 | t.* = try std.Thread.spawn(startGets, &context); | |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | 133 | for (putters) |t| |
lib/std/event/loop.zig+5-5| ... | ... | @@ -185,7 +185,7 @@ pub const Loop = struct { |
| 185 | 185 | errdefer self.deinitOsData(); |
| 186 | 186 | |
| 187 | 187 | if (!builtin.single_threaded) { |
| 188 | self.fs_thread = try Thread.spawn(self, posixFsRun); | |
| 188 | self.fs_thread = try Thread.spawn(posixFsRun, self); | |
| 189 | 189 | } |
| 190 | 190 | errdefer if (!builtin.single_threaded) { |
| 191 | 191 | self.posixFsRequest(&self.fs_end_request); |
| ... | ... | @@ -264,7 +264,7 @@ pub const Loop = struct { |
| 264 | 264 | } |
| 265 | 265 | } |
| 266 | 266 | 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); | |
| 268 | 268 | } |
| 269 | 269 | }, |
| 270 | 270 | .macos, .freebsd, .netbsd, .dragonfly, .openbsd => { |
| ... | ... | @@ -329,7 +329,7 @@ pub const Loop = struct { |
| 329 | 329 | } |
| 330 | 330 | } |
| 331 | 331 | 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); | |
| 333 | 333 | } |
| 334 | 334 | }, |
| 335 | 335 | .windows => { |
| ... | ... | @@ -378,7 +378,7 @@ pub const Loop = struct { |
| 378 | 378 | } |
| 379 | 379 | } |
| 380 | 380 | 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); | |
| 382 | 382 | } |
| 383 | 383 | }, |
| 384 | 384 | else => {}, |
| ... | ... | @@ -798,7 +798,7 @@ pub const Loop = struct { |
| 798 | 798 | .event = std.Thread.AutoResetEvent{}, |
| 799 | 799 | .is_running = true, |
| 800 | 800 | // 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), | |
| 802 | 802 | }; |
| 803 | 803 | } |
| 804 | 804 |
lib/std/fs/test.zig+1-1| ... | ... | @@ -762,7 +762,7 @@ test "open file with exclusive lock twice, make sure it waits" { |
| 762 | 762 | try evt.init(); |
| 763 | 763 | defer evt.deinit(); |
| 764 | 764 | |
| 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 }); | |
| 766 | 766 | defer t.wait(); |
| 767 | 767 | |
| 768 | 768 | 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" { |
| 161 | 161 | } |
| 162 | 162 | }; |
| 163 | 163 | |
| 164 | const t = try std.Thread.spawn(server.listen_address, S.clientFn); | |
| 164 | const t = try std.Thread.spawn(S.clientFn, server.listen_address); | |
| 165 | 165 | defer t.wait(); |
| 166 | 166 | |
| 167 | 167 | var client = try server.accept(); |
| ... | ... | @@ -285,7 +285,7 @@ test "listen on a unix socket, send bytes, receive bytes" { |
| 285 | 285 | } |
| 286 | 286 | }; |
| 287 | 287 | |
| 288 | const t = try std.Thread.spawn({}, S.clientFn); | |
| 288 | const t = try std.Thread.spawn(S.clientFn, {}); | |
| 289 | 289 | defer t.wait(); |
| 290 | 290 | |
| 291 | 291 | var client = try server.accept(); |
lib/std/once.zig+2-2| ... | ... | @@ -59,11 +59,11 @@ test "Once executes its function just once" { |
| 59 | 59 | defer for (threads) |handle| handle.wait(); |
| 60 | 60 | |
| 61 | 61 | for (threads) |*handle| { |
| 62 | handle.* = try std.Thread.spawn(@as(u8, 0), struct { | |
| 62 | handle.* = try std.Thread.spawn(struct { | |
| 63 | 63 | fn thread_fn(x: u8) void { |
| 64 | 64 | global_once.call(); |
| 65 | 65 | } |
| 66 | }.thread_fn); | |
| 66 | }.thread_fn, 0); | |
| 67 | 67 | } |
| 68 | 68 | } |
| 69 | 69 |
lib/std/os/test.zig+7-7| ... | ... | @@ -317,7 +317,7 @@ test "std.Thread.getCurrentId" { |
| 317 | 317 | if (builtin.single_threaded) return error.SkipZigTest; |
| 318 | 318 | |
| 319 | 319 | 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); | |
| 321 | 321 | const thread_id = thread.handle(); |
| 322 | 322 | thread.wait(); |
| 323 | 323 | if (Thread.use_pthreads) { |
| ... | ... | @@ -336,10 +336,10 @@ test "spawn threads" { |
| 336 | 336 | |
| 337 | 337 | var shared_ctx: i32 = 1; |
| 338 | 338 | |
| 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); | |
| 343 | 343 | |
| 344 | 344 | thread1.wait(); |
| 345 | 345 | thread2.wait(); |
| ... | ... | @@ -367,8 +367,8 @@ test "cpu count" { |
| 367 | 367 | |
| 368 | 368 | test "thread local storage" { |
| 369 | 369 | 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, {}); | |
| 372 | 372 | testTls({}); |
| 373 | 373 | thread1.wait(); |
| 374 | 374 | thread2.wait(); |
src/ThreadPool.zig+1-1| ... | ... | @@ -74,7 +74,7 @@ pub fn init(self: *ThreadPool, allocator: *std.mem.Allocator) !void { |
| 74 | 74 | try worker.idle_node.data.init(); |
| 75 | 75 | errdefer worker.idle_node.data.deinit(); |
| 76 | 76 | |
| 77 | worker.thread = try std.Thread.spawn(worker, Worker.run); | |
| 77 | worker.thread = try std.Thread.spawn(Worker.run, worker); | |
| 78 | 78 | } |
| 79 | 79 | } |
| 80 | 80 |