diff options
| author | Mitchell Hashimoto <mitchell.hashimoto@gmail.com> | 2022-11-05 18:51:39 -0700 |
|---|---|---|
| committer | Mitchell Hashimoto <mitchell.hashimoto@gmail.com> | 2022-11-05 19:31:28 -0700 |
| commit | e2d8ffc3c1a12acaa39e9e751aefc033a610347c (patch) | |
| tree | 5ccf6df715c7e9ae05e113d69fbcc1356a4ca254 /src/renderer/Thread.zig | |
| parent | 9a44e45785d853c3c52090005d5976daef0f2aed (diff) | |
renderer mailbox, focus message
Diffstat (limited to 'src/renderer/Thread.zig')
| -rw-r--r-- | src/renderer/Thread.zig | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/src/renderer/Thread.zig b/src/renderer/Thread.zig index 5fb10420a..feb31ebdc 100644 --- a/src/renderer/Thread.zig +++ b/src/renderer/Thread.zig @@ -7,11 +7,16 @@ const builtin = @import("builtin"); const glfw = @import("glfw"); const libuv = @import("libuv"); const renderer = @import("../renderer.zig"); -const gl = @import("../opengl.zig"); +const BlockingQueue = @import("../blocking_queue.zig").BlockingQueue; const Allocator = std.mem.Allocator; const log = std.log.scoped(.renderer_thread); +/// The type used for sending messages to the IO thread. For now this is +/// hardcoded with a capacity. We can make this a comptime parameter in +/// the future if we want it configurable. +const Mailbox = BlockingQueue(renderer.Message, 64); + /// The main event loop for the application. The user data of this loop /// is always the allocator used to create the loop. This is a convenience /// so that users of the loop always have an allocator. @@ -36,6 +41,10 @@ renderer: *renderer.Renderer, /// Pointer to the shared state that is used to generate the final render. state: *renderer.State, +/// 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. @@ -83,6 +92,10 @@ pub fn init( } }).callback); + // The mailbox for messaging this thread + var mailbox = try Mailbox.create(alloc); + errdefer mailbox.destroy(alloc); + return Thread{ .loop = loop, .wakeup = wakeup_h, @@ -91,6 +104,7 @@ pub fn init( .window = window, .renderer = renderer_impl, .state = state, + .mailbox = mailbox, }; } @@ -127,6 +141,9 @@ pub fn deinit(self: *Thread) void { _ = self.loop.run(.default) catch |err| log.err("error finalizing event loop: {}", .{err}); + // Nothing can possibly access the mailbox anymore, destroy it. + self.mailbox.destroy(alloc); + // Dealloc our allocator copy alloc.destroy(alloc_ptr); @@ -164,6 +181,23 @@ fn threadMain_(self: *Thread) !void { _ = try self.loop.run(.default); } +/// Drain the mailbox. +fn drainMailbox(self: *Thread) !void { + // This holds the mailbox lock for the duration of the drain. The + // expectation is that all our message handlers will be non-blocking + // ENOUGH to not mess up throughput on producers. + + var drain = self.mailbox.drain(); + defer drain.deinit(); + + while (drain.next()) |message| { + log.debug("mailbox message={}", .{message}); + switch (message) { + .focus => |v| try self.renderer.setFocus(v), + } + } +} + fn wakeupCallback(h: *libuv.Async) void { const t = h.getData(Thread) orelse { // This shouldn't happen so we log it. @@ -171,6 +205,11 @@ fn wakeupCallback(h: *libuv.Async) void { return; }; + // When we wake up, we check the mailbox. Mailbox producers should + // wake up our thread after publishing. + t.drainMailbox() catch |err| + log.err("error draining mailbox err={}", .{err}); + // If the timer is already active then we don't have to do anything. const active = t.render_h.isActive() catch true; if (active) return; |
