| ... | ... | @@ -1206,7 +1206,7 @@ pub fn Select(comptime U: type) type { |
| 1206 | 1206 | /// already been called and completed, or it has successfully been |
| 1207 | 1207 | /// assigned a unit of concurrency. |
| 1208 | 1208 | /// |
| 1209 | | /// After this is called, `wait` or `cancel` must be called before the |
| 1209 | /// After this is called, `await` or `cancel` must be called before the |
| 1210 | 1210 | /// select is deinitialized. |
| 1211 | 1211 | /// |
| 1212 | 1212 | /// Threadsafe. |
| ... | ... | @@ -1225,10 +1225,13 @@ pub fn Select(comptime U: type) type { |
| 1225 | 1225 | args: @TypeOf(args), |
| 1226 | 1226 | fn start(type_erased_context: *const anyopaque) Cancelable!void { |
| 1227 | 1227 | const context: *const @This() = @ptrCast(@alignCast(type_erased_context)); |
| 1228 | | const elem = @unionInit(U, @tagName(field), @call(.auto, function, context.args)); |
| 1228 | const raw_result = @call(.auto, function, context.args); |
| 1229 | const elem = @unionInit(U, @tagName(field), raw_result); |
| 1229 | 1230 | context.select.queue.putOneUncancelable(context.select.io, elem) catch |err| switch (err) { |
| 1230 | 1231 | error.Closed => unreachable, |
| 1231 | 1232 | }; |
| 1233 | if (@typeInfo(@TypeOf(raw_result)) == .error_union) |
| 1234 | raw_result catch |err| if (err == error.Canceled) return error.Canceled; |
| 1232 | 1235 | } |
| 1233 | 1236 | }; |
| 1234 | 1237 | const context: Context = .{ .select = s, .args = args }; |
| ... | ... | @@ -1236,6 +1239,46 @@ pub fn Select(comptime U: type) type { |
| 1236 | 1239 | s.io.vtable.groupAsync(s.io.userdata, &s.group, @ptrCast(&context), .of(Context), Context.start); |
| 1237 | 1240 | } |
| 1238 | 1241 | |
| 1242 | /// Calls `function` with `args` concurrently. The resource spawned is |
| 1243 | /// owned by the select. |
| 1244 | /// |
| 1245 | /// `function` must have return type matching the `field` field of `Union`. |
| 1246 | /// |
| 1247 | /// After this function returns successfully, it is guaranteed that |
| 1248 | /// `function` has been assigned a unit of concurrency, and `await` or |
| 1249 | /// `cancel` must be called before the select is deinitialized. |
| 1250 | /// |
| 1251 | /// |
| 1252 | /// Threadsafe. |
| 1253 | /// |
| 1254 | /// Related: |
| 1255 | /// * `Io.concurrent` |
| 1256 | /// * `Group.concurrent` |
| 1257 | pub fn concurrent( |
| 1258 | s: *S, |
| 1259 | comptime field: Field, |
| 1260 | function: anytype, |
| 1261 | args: std.meta.ArgsTuple(@TypeOf(function)), |
| 1262 | ) ConcurrentError!void { |
| 1263 | const Context = struct { |
| 1264 | select: *S, |
| 1265 | args: @TypeOf(args), |
| 1266 | fn start(type_erased_context: *const anyopaque) Cancelable!void { |
| 1267 | const context: *const @This() = @ptrCast(@alignCast(type_erased_context)); |
| 1268 | const raw_result = @call(.auto, function, context.args); |
| 1269 | const elem = @unionInit(U, @tagName(field), raw_result); |
| 1270 | context.select.queue.putOneUncancelable(context.select.io, elem) catch |err| switch (err) { |
| 1271 | error.Closed => unreachable, |
| 1272 | }; |
| 1273 | if (@typeInfo(@TypeOf(raw_result)) == .error_union) |
| 1274 | raw_result catch |err| if (err == error.Canceled) return error.Canceled; |
| 1275 | } |
| 1276 | }; |
| 1277 | const context: Context = .{ .select = s, .args = args }; |
| 1278 | try s.io.vtable.groupConcurrent(s.io.userdata, &s.group, @ptrCast(&context), .of(Context), Context.start); |
| 1279 | _ = @atomicRmw(usize, &s.outstanding, .Add, 1, .monotonic); |
| 1280 | } |
| 1281 | |
| 1239 | 1282 | /// Blocks until another task of the select finishes. |
| 1240 | 1283 | /// |
| 1241 | 1284 | /// Asserts there is at least one more `outstanding` task. |
| ... | ... | @@ -1249,12 +1292,12 @@ pub fn Select(comptime U: type) type { |
| 1249 | 1292 | }; |
| 1250 | 1293 | } |
| 1251 | 1294 | |
| 1252 | | /// Equivalent to `wait` but requests cancelation on all remaining |
| 1295 | /// Equivalent to `await` but requests cancelation on all remaining |
| 1253 | 1296 | /// tasks owned by the select. |
| 1254 | 1297 | /// |
| 1255 | 1298 | /// For a description of cancelation and cancelation points, see `Future.cancel`. |
| 1256 | 1299 | /// |
| 1257 | | /// It is illegal to call `wait` after this. |
| 1300 | /// It is illegal to call `await` after this. |
| 1258 | 1301 | /// |
| 1259 | 1302 | /// Idempotent. Not threadsafe. |
| 1260 | 1303 | pub fn cancel(s: *S) void { |