aboutsummaryrefslogtreecommitdiff
path: root/src/ThreadSafeQueue.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-10-18 00:23:35 -0700
committerAndrew Kelley <andrew@ziglang.org>2024-10-23 16:27:38 -0700
commit5ca54036ca0bc292ead681c03c8ac57e27a127db (patch)
tree17b151d68b2cb40c49d82af85286074be929db7d /src/ThreadSafeQueue.zig
parent2dcfa723767d284cef5eb180be7c080583ddbe25 (diff)
downloadzig-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.zig63
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;
+ }
+ };
+}