| ... | @@ -1,7 +1,8 @@ | ... | @@ -1,7 +1,8 @@ |
| 1 | const std = @import("std"); | | |
| 2 | const builtin = @import("builtin"); | 1 | const builtin = @import("builtin"); |
| 3 | const Pool = @This(); | 2 | const std = @import("std"); |
| | 3 | const assert = std.debug.assert; |
| 4 | const WaitGroup = @import("WaitGroup.zig"); | 4 | const WaitGroup = @import("WaitGroup.zig"); |
| | 5 | const Pool = @This(); |
| 5 | | 6 | |
| 6 | mutex: std.Thread.Mutex = .{}, | 7 | mutex: std.Thread.Mutex = .{}, |
| 7 | cond: std.Thread.Condition = .{}, | 8 | cond: std.Thread.Condition = .{}, |
| ... | @@ -307,3 +308,60 @@ pub fn waitAndWork(pool: *Pool, wait_group: *WaitGroup) void { | ... | @@ -307,3 +308,60 @@ pub fn waitAndWork(pool: *Pool, wait_group: *WaitGroup) void { |
| 307 | pub fn getIdCount(pool: *Pool) usize { | 308 | pub fn getIdCount(pool: *Pool) usize { |
| 308 | return @intCast(1 + pool.threads.len); | 309 | return @intCast(1 + pool.threads.len); |
| 309 | } | 310 | } |
| | 311 | |
| | 312 | const AsyncClosure = struct { |
| | 313 | func: *const fn (context: ?*anyopaque, result: *anyopaque) void, |
| | 314 | context: ?*anyopaque, |
| | 315 | run_node: std.Thread.Pool.RunQueue.Node = .{ .data = .{ .runFn = runFn } }, |
| | 316 | reset_event: std.Thread.ResetEvent, |
| | 317 | |
| | 318 | fn runFn(runnable: *std.Thread.Pool.Runnable, _: ?usize) void { |
| | 319 | const run_node: *std.Thread.Pool.RunQueue.Node = @fieldParentPtr("data", runnable); |
| | 320 | const closure: *@This() = @alignCast(@fieldParentPtr("run_node", run_node)); |
| | 321 | closure.func(closure.context, closure.resultPointer()); |
| | 322 | closure.reset_event.set(); |
| | 323 | } |
| | 324 | |
| | 325 | fn resultPointer(closure: *@This()) [*]u8 { |
| | 326 | const base: [*]u8 = @ptrCast(closure); |
| | 327 | return base + @sizeOf(@This()); |
| | 328 | } |
| | 329 | }; |
| | 330 | |
| | 331 | pub fn @"async"( |
| | 332 | userdata: ?*anyopaque, |
| | 333 | eager_result: []u8, |
| | 334 | context: ?*anyopaque, |
| | 335 | start: *const fn (context: ?*anyopaque, result: *anyopaque) void, |
| | 336 | ) ?*std.Io.AnyFuture { |
| | 337 | const pool: *std.Thread.Pool = @alignCast(@ptrCast(userdata)); |
| | 338 | pool.mutex.lock(); |
| | 339 | |
| | 340 | const gpa = pool.allocator; |
| | 341 | const n = @sizeOf(AsyncClosure) + eager_result.len; |
| | 342 | const closure: *AsyncClosure = @alignCast(@ptrCast(gpa.alignedAlloc(u8, @alignOf(AsyncClosure), n) catch { |
| | 343 | pool.mutex.unlock(); |
| | 344 | start(context, eager_result.ptr); |
| | 345 | return null; |
| | 346 | })); |
| | 347 | closure.* = .{ |
| | 348 | .func = start, |
| | 349 | .context = context, |
| | 350 | .reset_event = .{}, |
| | 351 | }; |
| | 352 | pool.run_queue.prepend(&closure.run_node); |
| | 353 | pool.mutex.unlock(); |
| | 354 | |
| | 355 | pool.cond.signal(); |
| | 356 | |
| | 357 | return @ptrCast(closure); |
| | 358 | } |
| | 359 | |
| | 360 | pub fn @"await"(userdata: ?*anyopaque, any_future: *std.Io.AnyFuture, result: []u8) void { |
| | 361 | const thread_pool: *std.Thread.Pool = @alignCast(@ptrCast(userdata)); |
| | 362 | const closure: *AsyncClosure = @ptrCast(@alignCast(any_future)); |
| | 363 | closure.reset_event.wait(); |
| | 364 | const base: [*]align(@alignOf(AsyncClosure)) u8 = @ptrCast(closure); |
| | 365 | @memcpy(result, (base + @sizeOf(AsyncClosure))[0..result.len]); |
| | 366 | thread_pool.allocator.free(base[0 .. @sizeOf(AsyncClosure) + result.len]); |
| | 367 | } |