| ... | @@ -580,6 +580,18 @@ pub const VTable = struct { | ... | @@ -580,6 +580,18 @@ pub const VTable = struct { |
| 580 | context_alignment: std.mem.Alignment, | 580 | context_alignment: std.mem.Alignment, |
| 581 | start: *const fn (context: *const anyopaque, result: *anyopaque) void, | 581 | start: *const fn (context: *const anyopaque, result: *anyopaque) void, |
| 582 | ) ?*AnyFuture, | 582 | ) ?*AnyFuture, |
| | 583 | /// Executes `start` asynchronously in a manner such that it cleans itself |
| | 584 | /// up. This mode does not support results, await, or cancel. |
| | 585 | /// |
| | 586 | /// Thread-safe. |
| | 587 | go: *const fn ( |
| | 588 | /// Corresponds to `Io.userdata`. |
| | 589 | userdata: ?*anyopaque, |
| | 590 | /// Copied and then passed to `start`. |
| | 591 | context: []const u8, |
| | 592 | context_alignment: std.mem.Alignment, |
| | 593 | start: *const fn (context: *const anyopaque) void, |
| | 594 | ) void, |
| 583 | /// This function is only called when `async` returns a non-null value. | 595 | /// This function is only called when `async` returns a non-null value. |
| 584 | /// | 596 | /// |
| 585 | /// Thread-safe. | 597 | /// Thread-safe. |
| ... | @@ -593,7 +605,6 @@ pub const VTable = struct { | ... | @@ -593,7 +605,6 @@ pub const VTable = struct { |
| 593 | result: []u8, | 605 | result: []u8, |
| 594 | result_alignment: std.mem.Alignment, | 606 | result_alignment: std.mem.Alignment, |
| 595 | ) void, | 607 | ) void, |
| 596 | | | |
| 597 | /// Equivalent to `await` but initiates cancel request. | 608 | /// Equivalent to `await` but initiates cancel request. |
| 598 | /// | 609 | /// |
| 599 | /// This function is only called when `async` returns a non-null value. | 610 | /// This function is only called when `async` returns a non-null value. |
| ... | @@ -671,14 +682,24 @@ pub fn Future(Result: type) type { | ... | @@ -671,14 +682,24 @@ pub fn Future(Result: type) type { |
| 671 | /// Idempotent. | 682 | /// Idempotent. |
| 672 | pub fn cancel(f: *@This(), io: Io) Result { | 683 | pub fn cancel(f: *@This(), io: Io) Result { |
| 673 | const any_future = f.any_future orelse return f.result; | 684 | const any_future = f.any_future orelse return f.result; |
| 674 | io.vtable.cancel(io.userdata, any_future, @ptrCast((&f.result)[0..1]), .of(Result)); | 685 | io.vtable.cancel( |
| | 686 | io.userdata, |
| | 687 | any_future, |
| | 688 | if (@sizeOf(Result) == 0) &.{} else @ptrCast((&f.result)[0..1]), // work around compiler bug |
| | 689 | .of(Result), |
| | 690 | ); |
| 675 | f.any_future = null; | 691 | f.any_future = null; |
| 676 | return f.result; | 692 | return f.result; |
| 677 | } | 693 | } |
| 678 | | 694 | |
| 679 | pub fn await(f: *@This(), io: Io) Result { | 695 | pub fn await(f: *@This(), io: Io) Result { |
| 680 | const any_future = f.any_future orelse return f.result; | 696 | const any_future = f.any_future orelse return f.result; |
| 681 | io.vtable.await(io.userdata, any_future, @ptrCast((&f.result)[0..1]), .of(Result)); | 697 | io.vtable.await( |
| | 698 | io.userdata, |
| | 699 | any_future, |
| | 700 | if (@sizeOf(Result) == 0) &.{} else @ptrCast((&f.result)[0..1]), // work around compiler bug |
| | 701 | .of(Result), |
| | 702 | ); |
| 682 | f.any_future = null; | 703 | f.any_future = null; |
| 683 | return f.result; | 704 | return f.result; |
| 684 | } | 705 | } |
| ... | @@ -996,7 +1017,7 @@ pub fn async(io: Io, function: anytype, args: anytype) Future(@typeInfo(@TypeOf( | ... | @@ -996,7 +1017,7 @@ pub fn async(io: Io, function: anytype, args: anytype) Future(@typeInfo(@TypeOf( |
| 996 | var future: Future(Result) = undefined; | 1017 | var future: Future(Result) = undefined; |
| 997 | future.any_future = io.vtable.async( | 1018 | future.any_future = io.vtable.async( |
| 998 | io.userdata, | 1019 | io.userdata, |
| 999 | @ptrCast((&future.result)[0..1]), | 1020 | if (@sizeOf(Result) == 0) &.{} else @ptrCast((&future.result)[0..1]), // work around compiler bug |
| 1000 | .of(Result), | 1021 | .of(Result), |
| 1001 | if (@sizeOf(Args) == 0) &.{} else @ptrCast((&args)[0..1]), // work around compiler bug | 1022 | if (@sizeOf(Args) == 0) &.{} else @ptrCast((&args)[0..1]), // work around compiler bug |
| 1002 | .of(Args), | 1023 | .of(Args), |
| ... | @@ -1005,6 +1026,24 @@ pub fn async(io: Io, function: anytype, args: anytype) Future(@typeInfo(@TypeOf( | ... | @@ -1005,6 +1026,24 @@ pub fn async(io: Io, function: anytype, args: anytype) Future(@typeInfo(@TypeOf( |
| 1005 | return future; | 1026 | return future; |
| 1006 | } | 1027 | } |
| 1007 | | 1028 | |
| | 1029 | /// Calls `function` with `args` asynchronously. The resource cleans itself up |
| | 1030 | /// when the function returns. Does not support await, cancel, or a return value. |
| | 1031 | pub fn go(io: Io, function: anytype, args: anytype) void { |
| | 1032 | const Args = @TypeOf(args); |
| | 1033 | const TypeErased = struct { |
| | 1034 | fn start(context: *const anyopaque) void { |
| | 1035 | const args_casted: *const Args = @alignCast(@ptrCast(context)); |
| | 1036 | @call(.auto, function, args_casted.*); |
| | 1037 | } |
| | 1038 | }; |
| | 1039 | io.vtable.go( |
| | 1040 | io.userdata, |
| | 1041 | if (@sizeOf(Args) == 0) &.{} else @ptrCast((&args)[0..1]), // work around compiler bug |
| | 1042 | .of(Args), |
| | 1043 | TypeErased.start, |
| | 1044 | ); |
| | 1045 | } |
| | 1046 | |
| 1008 | pub fn openFile(io: Io, dir: fs.Dir, sub_path: []const u8, flags: fs.File.OpenFlags) FileOpenError!fs.File { | 1047 | pub fn openFile(io: Io, dir: fs.Dir, sub_path: []const u8, flags: fs.File.OpenFlags) FileOpenError!fs.File { |
| 1009 | return io.vtable.openFile(io.userdata, dir, sub_path, flags); | 1048 | return io.vtable.openFile(io.userdata, dir, sub_path, flags); |
| 1010 | } | 1049 | } |