| ... | ... | @@ -8,7 +8,6 @@ const windows = std.os.windows; |
| 8 | 8 | const std = @import("../std.zig"); |
| 9 | 9 | const Allocator = std.mem.Allocator; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | | const WaitGroup = std.Thread.WaitGroup; |
| 12 | 11 | const posix = std.posix; |
| 13 | 12 | const Io = std.Io; |
| 14 | 13 | |
| ... | ... | @@ -101,10 +100,12 @@ pub fn io(pool: *Pool) Io { |
| 101 | 100 | .async = async, |
| 102 | 101 | .concurrent = concurrent, |
| 103 | 102 | .await = await, |
| 104 | | .asyncDetached = asyncDetached, |
| 105 | 103 | .cancel = cancel, |
| 106 | 104 | .cancelRequested = cancelRequested, |
| 107 | 105 | .select = select, |
| 106 | .groupAsync = groupAsync, |
| 107 | .groupWait = groupWait, |
| 108 | .groupCancel = groupCancel, |
| 108 | 109 | |
| 109 | 110 | .mutexLock = mutexLock, |
| 110 | 111 | .mutexUnlock = mutexUnlock, |
| ... | ... | @@ -279,7 +280,7 @@ fn async( |
| 279 | 280 | .func = start, |
| 280 | 281 | .context_offset = context_offset, |
| 281 | 282 | .result_offset = result_offset, |
| 282 | | .reset_event = .{}, |
| 283 | .reset_event = .unset, |
| 283 | 284 | .cancel_tid = 0, |
| 284 | 285 | .select_condition = null, |
| 285 | 286 | .runnable = .{ |
| ... | ... | @@ -347,7 +348,7 @@ fn concurrent( |
| 347 | 348 | .func = start, |
| 348 | 349 | .context_offset = context_offset, |
| 349 | 350 | .result_offset = result_offset, |
| 350 | | .reset_event = .{}, |
| 351 | .reset_event = .unset, |
| 351 | 352 | .cancel_tid = 0, |
| 352 | 353 | .select_condition = null, |
| 353 | 354 | .runnable = .{ |
| ... | ... | @@ -385,41 +386,47 @@ fn concurrent( |
| 385 | 386 | return @ptrCast(closure); |
| 386 | 387 | } |
| 387 | 388 | |
| 388 | | const DetachedClosure = struct { |
| 389 | const GroupClosure = struct { |
| 389 | 390 | pool: *Pool, |
| 391 | group: *Io.Group, |
| 390 | 392 | func: *const fn (context: *anyopaque) void, |
| 391 | 393 | runnable: Runnable, |
| 392 | 394 | context_alignment: std.mem.Alignment, |
| 393 | 395 | context_len: usize, |
| 394 | 396 | |
| 395 | 397 | fn start(runnable: *Runnable) void { |
| 396 | | const closure: *DetachedClosure = @alignCast(@fieldParentPtr("runnable", runnable)); |
| 398 | const closure: *GroupClosure = @alignCast(@fieldParentPtr("runnable", runnable)); |
| 397 | 399 | closure.func(closure.contextPointer()); |
| 400 | const group = closure.group; |
| 398 | 401 | const gpa = closure.pool.allocator; |
| 399 | 402 | free(closure, gpa); |
| 403 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); |
| 404 | const reset_event: *std.Thread.ResetEvent = @ptrCast(&group.context); |
| 405 | std.Thread.WaitGroup.finishStateless(group_state, reset_event); |
| 400 | 406 | } |
| 401 | 407 | |
| 402 | | fn free(closure: *DetachedClosure, gpa: Allocator) void { |
| 403 | | const base: [*]align(@alignOf(DetachedClosure)) u8 = @ptrCast(closure); |
| 408 | fn free(closure: *GroupClosure, gpa: Allocator) void { |
| 409 | const base: [*]align(@alignOf(GroupClosure)) u8 = @ptrCast(closure); |
| 404 | 410 | gpa.free(base[0..contextEnd(closure.context_alignment, closure.context_len)]); |
| 405 | 411 | } |
| 406 | 412 | |
| 407 | 413 | fn contextOffset(context_alignment: std.mem.Alignment) usize { |
| 408 | | return context_alignment.forward(@sizeOf(DetachedClosure)); |
| 414 | return context_alignment.forward(@sizeOf(GroupClosure)); |
| 409 | 415 | } |
| 410 | 416 | |
| 411 | 417 | fn contextEnd(context_alignment: std.mem.Alignment, context_len: usize) usize { |
| 412 | 418 | return contextOffset(context_alignment) + context_len; |
| 413 | 419 | } |
| 414 | 420 | |
| 415 | | fn contextPointer(closure: *DetachedClosure) [*]u8 { |
| 421 | fn contextPointer(closure: *GroupClosure) [*]u8 { |
| 416 | 422 | const base: [*]u8 = @ptrCast(closure); |
| 417 | 423 | return base + contextOffset(closure.context_alignment); |
| 418 | 424 | } |
| 419 | 425 | }; |
| 420 | 426 | |
| 421 | | fn asyncDetached( |
| 427 | fn groupAsync( |
| 422 | 428 | userdata: ?*anyopaque, |
| 429 | group: *Io.Group, |
| 423 | 430 | context: []const u8, |
| 424 | 431 | context_alignment: std.mem.Alignment, |
| 425 | 432 | start: *const fn (context: *const anyopaque) void, |
| ... | ... | @@ -428,17 +435,18 @@ fn asyncDetached( |
| 428 | 435 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 429 | 436 | const cpu_count = pool.cpu_count catch 1; |
| 430 | 437 | const gpa = pool.allocator; |
| 431 | | const n = DetachedClosure.contextEnd(context_alignment, context.len); |
| 432 | | const closure: *DetachedClosure = @ptrCast(@alignCast(gpa.alignedAlloc(u8, .of(DetachedClosure), n) catch { |
| 438 | const n = GroupClosure.contextEnd(context_alignment, context.len); |
| 439 | const closure: *GroupClosure = @ptrCast(@alignCast(gpa.alignedAlloc(u8, .of(GroupClosure), n) catch { |
| 433 | 440 | return start(context.ptr); |
| 434 | 441 | })); |
| 435 | 442 | closure.* = .{ |
| 436 | 443 | .pool = pool, |
| 444 | .group = group, |
| 437 | 445 | .func = start, |
| 438 | 446 | .context_alignment = context_alignment, |
| 439 | 447 | .context_len = context.len, |
| 440 | 448 | .runnable = .{ |
| 441 | | .start = DetachedClosure.start, |
| 449 | .start = GroupClosure.start, |
| 442 | 450 | .is_parallel = false, |
| 443 | 451 | }, |
| 444 | 452 | }; |
| ... | ... | @@ -466,10 +474,30 @@ fn asyncDetached( |
| 466 | 474 | pool.threads.appendAssumeCapacity(thread); |
| 467 | 475 | } |
| 468 | 476 | |
| 477 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); |
| 478 | std.Thread.WaitGroup.startStateless(group_state); |
| 479 | |
| 469 | 480 | pool.mutex.unlock(); |
| 470 | 481 | pool.cond.signal(); |
| 471 | 482 | } |
| 472 | 483 | |
| 484 | fn groupWait(userdata: ?*anyopaque, group: *Io.Group) void { |
| 485 | if (builtin.single_threaded) return; |
| 486 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 487 | _ = pool; |
| 488 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); |
| 489 | const reset_event: *std.Thread.ResetEvent = @ptrCast(&group.context); |
| 490 | std.Thread.WaitGroup.waitStateless(group_state, reset_event); |
| 491 | } |
| 492 | |
| 493 | fn groupCancel(userdata: ?*anyopaque, group: *Io.Group) void { |
| 494 | if (builtin.single_threaded) return; |
| 495 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 496 | _ = pool; |
| 497 | _ = group; |
| 498 | @panic("TODO threaded group cancel"); |
| 499 | } |
| 500 | |
| 473 | 501 | fn await( |
| 474 | 502 | userdata: ?*anyopaque, |
| 475 | 503 | any_future: *Io.AnyFuture, |
| ... | ... | @@ -968,7 +996,7 @@ fn select(userdata: ?*anyopaque, futures: []const *Io.AnyFuture) usize { |
| 968 | 996 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 969 | 997 | _ = pool; |
| 970 | 998 | |
| 971 | | var reset_event: std.Thread.ResetEvent = .{}; |
| 999 | var reset_event: std.Thread.ResetEvent = .unset; |
| 972 | 1000 | |
| 973 | 1001 | for (futures, 0..) |future, i| { |
| 974 | 1002 | const closure: *AsyncClosure = @ptrCast(@alignCast(future)); |