Function spawnWgId [src]

Runs func in the thread pool, calling WaitGroup.start beforehand, and WaitGroup.finish after it returns. The first argument passed to func is a dense usize thread id, the rest of the arguments are passed from args. Requires the pool to have been initialized with .track_ids = true. In the case that queuing the function call fails to allocate memory, or the target is single-threaded, the function is called directly.

Prototype

pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args: anytype) void

Parameters

pool: *Poolwait_group: *WaitGroup

Source

pub fn spawnWgId(pool: *Pool, wait_group: *WaitGroup, comptime func: anytype, args: anytype) void { wait_group.start(); if (builtin.single_threaded) { @call(.auto, func, .{0} ++ args); wait_group.finish(); return; } const Args = @TypeOf(args); const Closure = struct { arguments: Args, pool: *Pool, runnable: Runnable = .{ .runFn = runFn }, wait_group: *WaitGroup, fn runFn(runnable: *Runnable, id: ?usize) void { const closure: *@This() = @alignCast(@fieldParentPtr("runnable", runnable)); @call(.auto, func, .{id.?} ++ closure.arguments); closure.wait_group.finish(); // The thread pool's allocator is protected by the mutex. const mutex = &closure.pool.mutex; mutex.lock(); defer mutex.unlock(); closure.pool.allocator.destroy(closure); } }; { pool.mutex.lock(); const closure = pool.allocator.create(Closure) catch { const id: ?usize = pool.ids.getIndex(std.Thread.getCurrentId()); pool.mutex.unlock(); @call(.auto, func, .{id.?} ++ args); wait_group.finish(); return; }; closure.* = .{ .arguments = args, .pool = pool, .wait_group = wait_group, }; pool.run_queue.prepend(&closure.runnable.node); pool.mutex.unlock(); } // Notify waiting threads outside the lock to try and keep the critical section small. pool.cond.signal(); }