diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2024-10-18 00:23:35 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-10-23 16:27:38 -0700 |
| commit | 5ca54036ca0bc292ead681c03c8ac57e27a127db (patch) | |
| tree | 17b151d68b2cb40c49d82af85286074be929db7d /src/ThreadSafeQueue.zig | |
| parent | 2dcfa723767d284cef5eb180be7c080583ddbe25 (diff) | |
| download | zig-5ca54036ca0bc292ead681c03c8ac57e27a127db.tar.gz zig-5ca54036ca0bc292ead681c03c8ac57e27a127db.zip | |
move linker input file parsing to the compilation pipeline
Diffstat (limited to 'src/ThreadSafeQueue.zig')
| -rw-r--r-- | src/ThreadSafeQueue.zig | 63 |
1 files changed, 63 insertions, 0 deletions
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; + } + }; +} |
