From 8848e98271fc4b3c6b4f76796fd47db00a10b683 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 12 Nov 2025 10:07:21 -0800 Subject: [PATCH] terminal: search thread boilerplate (does nothing) --- src/terminal/search.zig | 1 + src/terminal/search/Thread.zig | 63 ++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/terminal/search/Thread.zig diff --git a/src/terminal/search.zig b/src/terminal/search.zig index a043973ff..6782f3e10 100644 --- a/src/terminal/search.zig +++ b/src/terminal/search.zig @@ -1,6 +1,7 @@ //! Search functionality for the terminal. pub const PageList = @import("search/pagelist.zig").PageListSearch; +pub const Thread = @import("search/Thread.zig"); test { @import("std").testing.refAllDecls(@This()); diff --git a/src/terminal/search/Thread.zig b/src/terminal/search/Thread.zig new file mode 100644 index 000000000..b9f98a9dc --- /dev/null +++ b/src/terminal/search/Thread.zig @@ -0,0 +1,63 @@ +//! Search thread that handles searching a terminal for a string match. +//! This is expected to run on a dedicated thread to try to prevent too much +//! overhead to other terminal read/write operations. +//! +//! The current architecture of search does acquire global locks for accessing +//! terminal data, so there's still added contention, but we do our best to +//! minimize this by trading off memory usage (copying data to minimize lock +//! time). +pub const Thread = @This(); + +const std = @import("std"); +const Allocator = std.mem.Allocator; +const BlockingQueue = @import("../../datastruct/main.zig").BlockingQueue; + +const log = std.log.scoped(.search_thread); + +/// Allocator used for some state +alloc: std.mem.Allocator, + +/// The mailbox that can be used to send this thread messages. Note +/// this is a blocking queue so if it is full you will get errors (or block). +mailbox: *Mailbox, + +/// Initialize the thread. This does not START the thread. This only sets +/// up all the internal state necessary prior to starting the thread. It +/// is up to the caller to start the thread with the threadMain entrypoint. +pub fn init(alloc: Allocator) Thread { + // The mailbox for messaging this thread + var mailbox = try Mailbox.create(alloc); + errdefer mailbox.destroy(alloc); + + return .{ + .alloc = alloc, + .mailbox = mailbox, + }; +} + +/// Clean up the thread. This is only safe to call once the thread +/// completes executing; the caller must join prior to this. +pub fn deinit(self: *Thread) void { + // Nothing can possibly access the mailbox anymore, destroy it. + self.mailbox.destroy(self.alloc); +} + +/// The main entrypoint for the thread. +pub fn threadMain(self: *Thread) void { + // Call child function so we can use errors... + self.threadMain_() catch |err| { + // In the future, we should expose this on the thread struct. + log.warn("search thread err={}", .{err}); + }; +} + +fn threadMain_(self: *Thread) !void { + defer log.debug("search thread exited", .{}); + _ = self; +} + +/// The type used for sending messages to the thread. +pub const Mailbox = BlockingQueue(Message, 64); + +/// The messages that can be sent to the thread. +pub const Message = union(enum) {};