| ... | @@ -933,6 +933,18 @@ pub const VTable = struct { | ... | @@ -933,6 +933,18 @@ pub const VTable = struct { |
| 933 | context_alignment: std.mem.Alignment, | 933 | context_alignment: std.mem.Alignment, |
| 934 | start: *const fn (context: *const anyopaque, result: *anyopaque) void, | 934 | start: *const fn (context: *const anyopaque, result: *anyopaque) void, |
| 935 | ) ?*AnyFuture, | 935 | ) ?*AnyFuture, |
| | 936 | /// Executes `start` asynchronously in a manner such that it cleans itself |
| | 937 | /// up. This mode does not support results, await, or cancel. |
| | 938 | /// |
| | 939 | /// Thread-safe. |
| | 940 | go: *const fn ( |
| | 941 | /// Corresponds to `Io.userdata`. |
| | 942 | userdata: ?*anyopaque, |
| | 943 | /// Copied and then passed to `start`. |
| | 944 | context: []const u8, |
| | 945 | context_alignment: std.mem.Alignment, |
| | 946 | start: *const fn (context: *const anyopaque) void, |
| | 947 | ) void, |
| 936 | /// This function is only called when `async` returns a non-null value. | 948 | /// This function is only called when `async` returns a non-null value. |
| 937 | /// | 949 | /// |
| 938 | /// Thread-safe. | 950 | /// Thread-safe. |
| ... | @@ -946,7 +958,6 @@ pub const VTable = struct { | ... | @@ -946,7 +958,6 @@ pub const VTable = struct { |
| 946 | result: []u8, | 958 | result: []u8, |
| 947 | result_alignment: std.mem.Alignment, | 959 | result_alignment: std.mem.Alignment, |
| 948 | ) void, | 960 | ) void, |
| 949 | | | |
| 950 | /// Equivalent to `await` but initiates cancel request. | 961 | /// Equivalent to `await` but initiates cancel request. |
| 951 | /// | 962 | /// |
| 952 | /// This function is only called when `async` returns a non-null value. | 963 | /// This function is only called when `async` returns a non-null value. |
| ... | @@ -1024,14 +1035,24 @@ pub fn Future(Result: type) type { | ... | @@ -1024,14 +1035,24 @@ pub fn Future(Result: type) type { |
| 1024 | /// Idempotent. | 1035 | /// Idempotent. |
| 1025 | pub fn cancel(f: *@This(), io: Io) Result { | 1036 | pub fn cancel(f: *@This(), io: Io) Result { |
| 1026 | const any_future = f.any_future orelse return f.result; | 1037 | const any_future = f.any_future orelse return f.result; |
| 1027 | io.vtable.cancel(io.userdata, any_future, @ptrCast((&f.result)[0..1]), .of(Result)); | 1038 | io.vtable.cancel( |
| | 1039 | io.userdata, |
| | 1040 | any_future, |
| | 1041 | if (@sizeOf(Result) == 0) &.{} else @ptrCast((&f.result)[0..1]), // work around compiler bug |
| | 1042 | .of(Result), |
| | 1043 | ); |
| 1028 | f.any_future = null; | 1044 | f.any_future = null; |
| 1029 | return f.result; | 1045 | return f.result; |
| 1030 | } | 1046 | } |
| 1031 | | 1047 | |
| 1032 | pub fn await(f: *@This(), io: Io) Result { | 1048 | pub fn await(f: *@This(), io: Io) Result { |
| 1033 | const any_future = f.any_future orelse return f.result; | 1049 | const any_future = f.any_future orelse return f.result; |
| 1034 | io.vtable.await(io.userdata, any_future, @ptrCast((&f.result)[0..1]), .of(Result)); | 1050 | io.vtable.await( |
| | 1051 | io.userdata, |
| | 1052 | any_future, |
| | 1053 | if (@sizeOf(Result) == 0) &.{} else @ptrCast((&f.result)[0..1]), // work around compiler bug |
| | 1054 | .of(Result), |
| | 1055 | ); |
| 1035 | f.any_future = null; | 1056 | f.any_future = null; |
| 1036 | return f.result; | 1057 | return f.result; |
| 1037 | } | 1058 | } |
| ... | @@ -1349,7 +1370,7 @@ pub fn async(io: Io, function: anytype, args: anytype) Future(@typeInfo(@TypeOf( | ... | @@ -1349,7 +1370,7 @@ pub fn async(io: Io, function: anytype, args: anytype) Future(@typeInfo(@TypeOf( |
| 1349 | var future: Future(Result) = undefined; | 1370 | var future: Future(Result) = undefined; |
| 1350 | future.any_future = io.vtable.async( | 1371 | future.any_future = io.vtable.async( |
| 1351 | io.userdata, | 1372 | io.userdata, |
| 1352 | @ptrCast((&future.result)[0..1]), | 1373 | if (@sizeOf(Result) == 0) &.{} else @ptrCast((&future.result)[0..1]), // work around compiler bug |
| 1353 | .of(Result), | 1374 | .of(Result), |
| 1354 | if (@sizeOf(Args) == 0) &.{} else @ptrCast((&args)[0..1]), // work around compiler bug | 1375 | if (@sizeOf(Args) == 0) &.{} else @ptrCast((&args)[0..1]), // work around compiler bug |
| 1355 | .of(Args), | 1376 | .of(Args), |
| ... | @@ -1358,6 +1379,24 @@ pub fn async(io: Io, function: anytype, args: anytype) Future(@typeInfo(@TypeOf( | ... | @@ -1358,6 +1379,24 @@ pub fn async(io: Io, function: anytype, args: anytype) Future(@typeInfo(@TypeOf( |
| 1358 | return future; | 1379 | return future; |
| 1359 | } | 1380 | } |
| 1360 | | 1381 | |
| | 1382 | /// Calls `function` with `args` asynchronously. The resource cleans itself up |
| | 1383 | /// when the function returns. Does not support await, cancel, or a return value. |
| | 1384 | pub fn go(io: Io, function: anytype, args: anytype) void { |
| | 1385 | const Args = @TypeOf(args); |
| | 1386 | const TypeErased = struct { |
| | 1387 | fn start(context: *const anyopaque) void { |
| | 1388 | const args_casted: *const Args = @alignCast(@ptrCast(context)); |
| | 1389 | @call(.auto, function, args_casted.*); |
| | 1390 | } |
| | 1391 | }; |
| | 1392 | io.vtable.go( |
| | 1393 | io.userdata, |
| | 1394 | if (@sizeOf(Args) == 0) &.{} else @ptrCast((&args)[0..1]), // work around compiler bug |
| | 1395 | .of(Args), |
| | 1396 | TypeErased.start, |
| | 1397 | ); |
| | 1398 | } |
| | 1399 | |
| 1361 | pub fn openFile(io: Io, dir: fs.Dir, sub_path: []const u8, flags: fs.File.OpenFlags) FileOpenError!fs.File { | 1400 | pub fn openFile(io: Io, dir: fs.Dir, sub_path: []const u8, flags: fs.File.OpenFlags) FileOpenError!fs.File { |
| 1362 | return io.vtable.openFile(io.userdata, dir, sub_path, flags); | 1401 | return io.vtable.openFile(io.userdata, dir, sub_path, flags); |
| 1363 | } | 1402 | } |