1const std = @import("std");
2const assert = std.debug.assert;
3const Allocator = std.mem.Allocator;
4
5/// A thread-safe queue where any number of threads may consume items,
6/// and any of those same threads may concurrently append new items.
7///
8/// This relevant for multi-threaded compilation, where new tasks should
9/// be picked up by new threads
10pub fn Queue(comptime Item: type) type {
11 return struct {
12 const Node = std.SinglyLinkedList(Item).Node;
13
14 head: ?*Node = null,
15 tail: ?*Node = null,
16
17 object_pool: std.SinglyLinkedList(Item) = .{},
18
19 pub fn init(thread_count: usize) @This() {
20 assert(thread_count != 0);
21 if (thread_count != 1)
22 @panic("Multi-threaded queue is not yet implemented");
23 return .{};
24 }
25
26 pub fn push(queue: *@This(), allocator: Allocator, item: Item) !void {
27 const new_node = queue.object_pool.popFirst() orelse
28 try allocator.create(Node);
29
30 new_node.* = .{ .data = item };
31 if (queue.tail) |tail| {
32 tail.next = new_node;
33 } else {
34 queue.head = new_node;
35 }
36 queue.tail = new_node;
37 }
38
39 pub fn next(queue: *@This()) ?Item {
40 const head = queue.head orelse return null;
41 queue.head = head.next;
42 if (queue.head == null) queue.tail = null;
43 queue.object_pool.prepend(head);
44 return head.data;
45 }
46 };
47}