From 5ca54036ca0bc292ead681c03c8ac57e27a127db Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 18 Oct 2024 00:23:35 -0700 Subject: move linker input file parsing to the compilation pipeline --- src/ThreadSafeQueue.zig | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/ThreadSafeQueue.zig (limited to 'src/ThreadSafeQueue.zig') diff --git a/src/ThreadSafeQueue.zig b/src/ThreadSafeQueue.zig new file mode 100644 index 0000000000..b014017736 --- /dev/null +++ b/src/ThreadSafeQueue.zig @@ -0,0 +1,63 @@ +const std = @import("std"); +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; + +pub fn ThreadSafeQueue(comptime T: type) type { + return struct { + worker_owned: std.ArrayListUnmanaged(T), + /// Protected by `mutex`. + shared: std.ArrayListUnmanaged(T), + mutex: std.Thread.Mutex, + state: State, + + const Self = @This(); + + pub const State = enum { wait, run }; + + pub const empty: Self = .{ + .worker_owned = .empty, + .shared = .empty, + .mutex = .{}, + .state = .wait, + }; + + pub fn deinit(self: *Self, gpa: Allocator) void { + self.worker_owned.deinit(gpa); + self.shared.deinit(gpa); + self.* = undefined; + } + + /// Must be called from the worker thread. + pub fn check(self: *Self) ?[]T { + assert(self.worker_owned.items.len == 0); + { + self.mutex.lock(); + defer self.mutex.unlock(); + assert(self.state == .run); + if (self.shared.items.len == 0) { + self.state = .wait; + return null; + } + std.mem.swap(std.ArrayListUnmanaged(T), &self.worker_owned, &self.shared); + } + const result = self.worker_owned.items; + self.worker_owned.clearRetainingCapacity(); + return result; + } + + /// Adds items to the queue, returning true if and only if the worker + /// thread is waiting. Thread-safe. + /// Not safe to call from the worker thread. + pub fn enqueue(self: *Self, gpa: Allocator, items: []const T) error{OutOfMemory}!bool { + self.mutex.lock(); + defer self.mutex.unlock(); + try self.shared.appendSlice(gpa, items); + const was_waiting = switch (self.state) { + .run => false, + .wait => true, + }; + self.state = .run; + return was_waiting; + } + }; +} -- cgit v1.2.3