authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2025-08-25 20:30:20+02:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2025-08-26 09:39:09+02:00
log6d4dbf05effa3afeb650aeea17683d5de4e6429c
tree29458c85d0cb2cd28a48c2c7f0c47d07222f978b
parent3e77317261e3da50ac55be0c14bc00192ee93166
signaturelock-open Commit is signed but in an unrecognized format.

Compilation: use std.Deque

And delete DeprecatedLinearFifo from the source tree.

3 files changed, 22 insertions(+), 192 deletions(-)

lib/std/deque.zig+1-1
......@@ -143,7 +143,7 @@ pub fn Deque(comptime T: type) type {
143143 deque.len += 1;
144144 }
145145
146 /// Add one item to the front of the deque.
146 /// Add one item to the back of the deque.
147147 ///
148148 /// Invalidates element pointers if additional memory is needed.
149149 pub fn pushBack(deque: *Self, gpa: Allocator, item: T) error{OutOfMemory}!void {
src/Compilation.zig+21-22
......@@ -45,8 +45,6 @@ const Builtin = @import("Builtin.zig");
4545const LlvmObject = @import("codegen/llvm.zig").Object;
4646const dev = @import("dev.zig");
4747
48const DeprecatedLinearFifo = @import("deprecated.zig").LinearFifo;
49
5048pub const Config = @import("Compilation/Config.zig");
5149
5250/// General-purpose allocator. Used for both temporary and long-term storage.
......@@ -124,20 +122,21 @@ work_queues: [
124122 }
125123 break :len len;
126124 }
127]DeprecatedLinearFifo(Job),
125]std.Deque(Job),
128126
129127/// These jobs are to invoke the Clang compiler to create an object file, which
130128/// gets linked with the Compilation.
131c_object_work_queue: DeprecatedLinearFifo(*CObject),
129c_object_work_queue: std.Deque(*CObject),
132130
133131/// These jobs are to invoke the RC compiler to create a compiled resource file (.res), which
134132/// gets linked with the Compilation.
135win32_resource_work_queue: if (dev.env.supports(.win32_resource)) DeprecatedLinearFifo(*Win32Resource) else struct {
136 pub fn ensureUnusedCapacity(_: @This(), _: u0) error{}!void {}
137 pub fn readItem(_: @This()) ?noreturn {
133win32_resource_work_queue: if (dev.env.supports(.win32_resource)) std.Deque(*Win32Resource) else struct {
134 pub const empty: @This() = .{};
135 pub fn ensureUnusedCapacity(_: @This(), _: Allocator, _: u0) error{}!void {}
136 pub fn popFront(_: @This()) ?noreturn {
138137 return null;
139138 }
140 pub fn deinit(_: @This()) void {}
139 pub fn deinit(_: @This(), _: Allocator) void {}
141140},
142141
143142/// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator.
......@@ -2231,9 +2230,9 @@ pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options
22312230 .root_mod = options.root_mod,
22322231 .config = options.config,
22332232 .dirs = options.dirs,
2234 .work_queues = @splat(.init(gpa)),
2235 .c_object_work_queue = .init(gpa),
2236 .win32_resource_work_queue = if (dev.env.supports(.win32_resource)) .init(gpa) else .{},
2233 .work_queues = @splat(.empty),
2234 .c_object_work_queue = .empty,
2235 .win32_resource_work_queue = .empty,
22372236 .c_source_files = options.c_source_files,
22382237 .rc_source_files = options.rc_source_files,
22392238 .cache_parent = cache,
......@@ -2699,9 +2698,9 @@ pub fn destroy(comp: *Compilation) void {
26992698 if (comp.zcu) |zcu| zcu.deinit();
27002699 comp.cache_use.deinit();
27012700
2702 for (&comp.work_queues) |*work_queue| work_queue.deinit();
2703 comp.c_object_work_queue.deinit();
2704 comp.win32_resource_work_queue.deinit();
2701 for (&comp.work_queues) |*work_queue| work_queue.deinit(gpa);
2702 comp.c_object_work_queue.deinit(gpa);
2703 comp.win32_resource_work_queue.deinit(gpa);
27052704
27062705 for (comp.windows_libs.keys()) |windows_lib| gpa.free(windows_lib);
27072706 comp.windows_libs.deinit(gpa);
......@@ -3016,17 +3015,17 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
30163015
30173016 // For compiling C objects, we rely on the cache hash system to avoid duplicating work.
30183017 // Add a Job for each C object.
3019 try comp.c_object_work_queue.ensureUnusedCapacity(comp.c_object_table.count());
3018 try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_object_table.count());
30203019 for (comp.c_object_table.keys()) |c_object| {
3021 comp.c_object_work_queue.writeItemAssumeCapacity(c_object);
3020 comp.c_object_work_queue.pushBackAssumeCapacity(c_object);
30223021 try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{c_object.src.src_path}));
30233022 }
30243023
30253024 // For compiling Win32 resources, we rely on the cache hash system to avoid duplicating work.
30263025 // Add a Job for each Win32 resource file.
3027 try comp.win32_resource_work_queue.ensureUnusedCapacity(comp.win32_resource_table.count());
3026 try comp.win32_resource_work_queue.ensureUnusedCapacity(gpa, comp.win32_resource_table.count());
30283027 for (comp.win32_resource_table.keys()) |win32_resource| {
3029 comp.win32_resource_work_queue.writeItemAssumeCapacity(win32_resource);
3028 comp.win32_resource_work_queue.pushBackAssumeCapacity(win32_resource);
30303029 switch (win32_resource.src) {
30313030 .rc => |f| {
30323031 try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{f.src_path}));
......@@ -4869,14 +4868,14 @@ fn performAllTheWork(
48694868 }
48704869 }
48714870
4872 while (comp.c_object_work_queue.readItem()) |c_object| {
4871 while (comp.c_object_work_queue.popFront()) |c_object| {
48734872 comp.link_task_queue.startPrelinkItem();
48744873 comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateCObject, .{
48754874 comp, c_object, main_progress_node,
48764875 });
48774876 }
48784877
4879 while (comp.win32_resource_work_queue.readItem()) |win32_resource| {
4878 while (comp.win32_resource_work_queue.popFront()) |win32_resource| {
48804879 comp.link_task_queue.startPrelinkItem();
48814880 comp.thread_pool.spawnWg(&comp.link_task_wait_group, workerUpdateWin32Resource, .{
48824881 comp, win32_resource, main_progress_node,
......@@ -4996,7 +4995,7 @@ fn performAllTheWork(
49964995 }
49974996
49984997 work: while (true) {
4999 for (&comp.work_queues) |*work_queue| if (work_queue.readItem()) |job| {
4998 for (&comp.work_queues) |*work_queue| if (work_queue.popFront()) |job| {
50004999 try processOneJob(@intFromEnum(Zcu.PerThread.Id.main), comp, job);
50015000 continue :work;
50025001 };
......@@ -5025,7 +5024,7 @@ fn performAllTheWork(
50255024const JobError = Allocator.Error;
50265025
50275026pub fn queueJob(comp: *Compilation, job: Job) !void {
5028 try comp.work_queues[Job.stage(job)].writeItem(job);
5027 try comp.work_queues[Job.stage(job)].pushBack(comp.gpa, job);
50295028}
50305029
50315030pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void {
src/deprecated.zig deleted-169
......@@ -1,169 +0,0 @@
1//! Deprecated. Stop using this API
2
3const std = @import("std");
4const math = std.math;
5const mem = std.mem;
6const Allocator = mem.Allocator;
7const assert = std.debug.assert;
8const testing = std.testing;
9
10pub fn LinearFifo(comptime T: type) type {
11 return struct {
12 allocator: Allocator,
13 buf: []T,
14 head: usize,
15 count: usize,
16
17 const Self = @This();
18
19 pub fn init(allocator: Allocator) Self {
20 return .{
21 .allocator = allocator,
22 .buf = &.{},
23 .head = 0,
24 .count = 0,
25 };
26 }
27
28 pub fn deinit(self: *Self) void {
29 self.allocator.free(self.buf);
30 self.* = undefined;
31 }
32
33 pub fn realign(self: *Self) void {
34 if (self.buf.len - self.head >= self.count) {
35 mem.copyForwards(T, self.buf[0..self.count], self.buf[self.head..][0..self.count]);
36 self.head = 0;
37 } else {
38 var tmp: [4096 / 2 / @sizeOf(T)]T = undefined;
39
40 while (self.head != 0) {
41 const n = @min(self.head, tmp.len);
42 const m = self.buf.len - n;
43 @memcpy(tmp[0..n], self.buf[0..n]);
44 mem.copyForwards(T, self.buf[0..m], self.buf[n..][0..m]);
45 @memcpy(self.buf[m..][0..n], tmp[0..n]);
46 self.head -= n;
47 }
48 }
49 { // set unused area to undefined
50 const unused = mem.sliceAsBytes(self.buf[self.count..]);
51 @memset(unused, undefined);
52 }
53 }
54
55 /// Ensure that the buffer can fit at least `size` items
56 pub fn ensureTotalCapacity(self: *Self, size: usize) !void {
57 if (self.buf.len >= size) return;
58 self.realign();
59 const new_size = math.ceilPowerOfTwo(usize, size) catch return error.OutOfMemory;
60 self.buf = try self.allocator.realloc(self.buf, new_size);
61 }
62
63 /// Makes sure at least `size` items are unused
64 pub fn ensureUnusedCapacity(self: *Self, size: usize) error{OutOfMemory}!void {
65 if (self.writableLength() >= size) return;
66
67 return try self.ensureTotalCapacity(math.add(usize, self.count, size) catch return error.OutOfMemory);
68 }
69
70 /// Returns a writable slice from the 'read' end of the fifo
71 fn readableSliceMut(self: Self, offset: usize) []T {
72 if (offset > self.count) return &[_]T{};
73
74 var start = self.head + offset;
75 if (start >= self.buf.len) {
76 start -= self.buf.len;
77 return self.buf[start .. start + (self.count - offset)];
78 } else {
79 const end = @min(self.head + self.count, self.buf.len);
80 return self.buf[start..end];
81 }
82 }
83
84 /// Discard first `count` items in the fifo
85 pub fn discard(self: *Self, count: usize) void {
86 assert(count <= self.count);
87 { // set old range to undefined. Note: may be wrapped around
88 const slice = self.readableSliceMut(0);
89 if (slice.len >= count) {
90 const unused = mem.sliceAsBytes(slice[0..count]);
91 @memset(unused, undefined);
92 } else {
93 const unused = mem.sliceAsBytes(slice[0..]);
94 @memset(unused, undefined);
95 const unused2 = mem.sliceAsBytes(self.readableSliceMut(slice.len)[0 .. count - slice.len]);
96 @memset(unused2, undefined);
97 }
98 }
99 var head = self.head + count;
100 // Note it is safe to do a wrapping subtract as
101 // bitwise & with all 1s is a noop
102 head &= self.buf.len -% 1;
103 self.head = head;
104 self.count -= count;
105 }
106
107 /// Read the next item from the fifo
108 pub fn readItem(self: *Self) ?T {
109 if (self.count == 0) return null;
110
111 const c = self.buf[self.head];
112 self.discard(1);
113 return c;
114 }
115
116 /// Returns number of items available in fifo
117 pub fn writableLength(self: Self) usize {
118 return self.buf.len - self.count;
119 }
120
121 /// Returns the first section of writable buffer.
122 /// Note that this may be of length 0
123 pub fn writableSlice(self: Self, offset: usize) []T {
124 if (offset > self.buf.len) return &[_]T{};
125
126 const tail = self.head + offset + self.count;
127 if (tail < self.buf.len) {
128 return self.buf[tail..];
129 } else {
130 return self.buf[tail - self.buf.len ..][0 .. self.writableLength() - offset];
131 }
132 }
133
134 /// Update the tail location of the buffer (usually follows use of writable/writableWithSize)
135 pub fn update(self: *Self, count: usize) void {
136 assert(self.count + count <= self.buf.len);
137 self.count += count;
138 }
139
140 /// Appends the data in `src` to the fifo.
141 /// You must have ensured there is enough space.
142 pub fn writeAssumeCapacity(self: *Self, src: []const T) void {
143 assert(self.writableLength() >= src.len);
144
145 var src_left = src;
146 while (src_left.len > 0) {
147 const writable_slice = self.writableSlice(0);
148 assert(writable_slice.len != 0);
149 const n = @min(writable_slice.len, src_left.len);
150 @memcpy(writable_slice[0..n], src_left[0..n]);
151 self.update(n);
152 src_left = src_left[n..];
153 }
154 }
155
156 /// Write a single item to the fifo
157 pub fn writeItem(self: *Self, item: T) !void {
158 try self.ensureUnusedCapacity(1);
159 return self.writeItemAssumeCapacity(item);
160 }
161
162 pub fn writeItemAssumeCapacity(self: *Self, item: T) void {
163 var tail = self.head + self.count;
164 tail &= self.buf.len - 1;
165 self.buf[tail] = item;
166 self.update(1);
167 }
168 };
169}