diff options
Diffstat (limited to 'src/selection_pipe.zig')
| -rw-r--r-- | src/selection_pipe.zig | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/selection_pipe.zig b/src/selection_pipe.zig index 65c4c7fd..c1104010 100644 --- a/src/selection_pipe.zig +++ b/src/selection_pipe.zig @@ -78,6 +78,55 @@ pub const Response = struct { } }; +/// The in-flight set a host keeps while pipes run off its loop. +/// +/// tty.zig and gui.zig each had this verbatim — same `finish` walk, same +/// `cancelAll`, same 16 — differing only in whether `add` asserted or returned +/// a bool. It lives here beside the Job it tracks so a third host (the AppKit +/// shell, which had no pipe support at all) does not have to grow a fourth. +/// +/// Bounded on purpose: a filter is a user gesture, and sixteen concurrent ones +/// is already more than anybody means. `add` returning false is the host's cue +/// to answer the request as failed rather than to queue it. +pub const Tasks = struct { + pub const capacity = 16; + + pub const Task = struct { + id: u32, + future: std.Io.Future(anyerror!void), + }; + + items: [capacity]Task = undefined, + len: usize = 0, + + pub fn full(tasks: *const Tasks) bool { + return tasks.len == tasks.items.len; + } + + pub fn add(tasks: *Tasks, task: Task) bool { + if (tasks.full()) return false; + tasks.items[tasks.len] = task; + tasks.len += 1; + return true; + } + + /// Join the one that answered and drop it, preserving order so `cancelAll` + /// stays deterministic. + pub fn finish(tasks: *Tasks, io: std.Io, id: u32) void { + for (tasks.items[0..tasks.len], 0..) |*task, i| if (task.id == id) { + task.future.await(io) catch {}; + tasks.len -= 1; + std.mem.copyForwards(Task, tasks.items[i..tasks.len], tasks.items[i + 1 .. tasks.len + 1]); + return; + }; + } + + pub fn cancelAll(tasks: *Tasks, io: std.Io) void { + for (tasks.items[0..tasks.len]) |*task| task.future.cancel(io) catch {}; + tasks.len = 0; + } +}; + const WriterContext = struct { io: std.Io, file: std.Io.File, |
