| ... | ... | @@ -309,46 +309,80 @@ pub fn getIdCount(pool: *Pool) usize { |
| 309 | 309 | return @intCast(1 + pool.threads.len); |
| 310 | 310 | } |
| 311 | 311 | |
| 312 | pub fn io(pool: *Pool) std.Io { |
| 313 | return .{ |
| 314 | .userdata = pool, |
| 315 | .vtable = &.{ |
| 316 | .@"async" = @"async", |
| 317 | .@"await" = @"await", |
| 318 | }, |
| 319 | }; |
| 320 | } |
| 321 | |
| 312 | 322 | const AsyncClosure = struct { |
| 313 | | func: *const fn (context: ?*anyopaque, result: *anyopaque) void, |
| 314 | | context: ?*anyopaque, |
| 323 | func: *const fn (context: *anyopaque, result: *anyopaque) void, |
| 315 | 324 | run_node: std.Thread.Pool.RunQueue.Node = .{ .data = .{ .runFn = runFn } }, |
| 316 | 325 | reset_event: std.Thread.ResetEvent, |
| 326 | context_offset: usize, |
| 327 | result_offset: usize, |
| 317 | 328 | |
| 318 | 329 | fn runFn(runnable: *std.Thread.Pool.Runnable, _: ?usize) void { |
| 319 | 330 | 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()); |
| 331 | const closure: *AsyncClosure = @alignCast(@fieldParentPtr("run_node", run_node)); |
| 332 | closure.func(closure.contextPointer(), closure.resultPointer()); |
| 322 | 333 | closure.reset_event.set(); |
| 323 | 334 | } |
| 324 | 335 | |
| 325 | | fn resultPointer(closure: *@This()) [*]u8 { |
| 336 | fn contextOffset(context_alignment: std.mem.Alignment) usize { |
| 337 | return context_alignment.forward(@sizeOf(AsyncClosure)); |
| 338 | } |
| 339 | |
| 340 | fn resultOffset( |
| 341 | context_alignment: std.mem.Alignment, |
| 342 | context_len: usize, |
| 343 | result_alignment: std.mem.Alignment, |
| 344 | ) usize { |
| 345 | return result_alignment.forward(contextOffset(context_alignment) + context_len); |
| 346 | } |
| 347 | |
| 348 | fn resultPointer(closure: *AsyncClosure) [*]u8 { |
| 349 | const base: [*]u8 = @ptrCast(closure); |
| 350 | return base + closure.result_offset; |
| 351 | } |
| 352 | |
| 353 | fn contextPointer(closure: *AsyncClosure) [*]u8 { |
| 326 | 354 | const base: [*]u8 = @ptrCast(closure); |
| 327 | | return base + @sizeOf(@This()); |
| 355 | return base + closure.context_offset; |
| 328 | 356 | } |
| 329 | 357 | }; |
| 330 | 358 | |
| 331 | 359 | pub fn @"async"( |
| 332 | 360 | userdata: ?*anyopaque, |
| 333 | | eager_result: []u8, |
| 334 | | context: ?*anyopaque, |
| 335 | | start: *const fn (context: ?*anyopaque, result: *anyopaque) void, |
| 361 | result: []u8, |
| 362 | result_alignment: std.mem.Alignment, |
| 363 | context: []const u8, |
| 364 | context_alignment: std.mem.Alignment, |
| 365 | start: *const fn (context: *const anyopaque, result: *anyopaque) void, |
| 336 | 366 | ) ?*std.Io.AnyFuture { |
| 337 | 367 | const pool: *std.Thread.Pool = @alignCast(@ptrCast(userdata)); |
| 338 | 368 | pool.mutex.lock(); |
| 339 | 369 | |
| 340 | 370 | const gpa = pool.allocator; |
| 341 | | const n = @sizeOf(AsyncClosure) + eager_result.len; |
| 371 | const context_offset = context_alignment.forward(@sizeOf(AsyncClosure)); |
| 372 | const result_offset = result_alignment.forward(context_offset + context.len); |
| 373 | const n = result_offset + result.len; |
| 342 | 374 | const closure: *AsyncClosure = @alignCast(@ptrCast(gpa.alignedAlloc(u8, @alignOf(AsyncClosure), n) catch { |
| 343 | 375 | pool.mutex.unlock(); |
| 344 | | start(context, eager_result.ptr); |
| 376 | start(context.ptr, result.ptr); |
| 345 | 377 | return null; |
| 346 | 378 | })); |
| 347 | 379 | closure.* = .{ |
| 348 | 380 | .func = start, |
| 349 | | .context = context, |
| 381 | .context_offset = context_offset, |
| 382 | .result_offset = result_offset, |
| 350 | 383 | .reset_event = .{}, |
| 351 | 384 | }; |
| 385 | @memcpy(closure.contextPointer()[0..context.len], context); |
| 352 | 386 | pool.run_queue.prepend(&closure.run_node); |
| 353 | 387 | pool.mutex.unlock(); |
| 354 | 388 | |