authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-04-04 15:19:55-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-02 16:30:59-07:00
log0c0ea7844eaa4de5d470cb9c20d4af1e22032400
treef24b4008b3988a04aadb3968fc2ae8f3be91e66f
parent61c38d77c66fe707bba41e43e59f2c727cbe7bb7

Io: update for new linked list API


2 files changed, 43 insertions(+), 46 deletions(-)

lib/std/Io.zig+40-42
......@@ -917,17 +917,19 @@ pub const TypeErasedQueue = struct {
917917 put_index: usize,
918918 get_index: usize,
919919
920 putters: std.DoublyLinkedList(PutNode),
921 getters: std.DoublyLinkedList(GetNode),
920 putters: std.DoublyLinkedList,
921 getters: std.DoublyLinkedList,
922922
923 const PutNode = struct {
923 const Put = struct {
924924 remaining: []const u8,
925925 condition: Condition,
926 node: std.DoublyLinkedList.Node,
926927 };
927928
928 const GetNode = struct {
929 const Get = struct {
929930 remaining: []u8,
930931 condition: Condition,
932 node: std.DoublyLinkedList.Node,
931933 };
932934
933935 pub fn init(buffer: []u8) TypeErasedQueue {
......@@ -952,16 +954,16 @@ pub const TypeErasedQueue = struct {
952954
953955 var remaining = elements;
954956 while (true) {
955 const getter = q.getters.popFirst() orelse break;
956 const copy_len = @min(getter.data.remaining.len, remaining.len);
957 @memcpy(getter.data.remaining[0..copy_len], remaining[0..copy_len]);
957 const getter: *Get = @fieldParentPtr("node", q.getters.popFirst() orelse break);
958 const copy_len = @min(getter.remaining.len, remaining.len);
959 @memcpy(getter.remaining[0..copy_len], remaining[0..copy_len]);
958960 remaining = remaining[copy_len..];
959 getter.data.remaining = getter.data.remaining[copy_len..];
960 if (getter.data.remaining.len == 0) {
961 getter.data.condition.signal(io);
961 getter.remaining = getter.remaining[copy_len..];
962 if (getter.remaining.len == 0) {
963 getter.condition.signal(io);
962964 continue;
963965 }
964 q.getters.prepend(getter);
966 q.getters.prepend(&getter.node);
965967 assert(remaining.len == 0);
966968 return elements.len;
967969 }
......@@ -987,12 +989,10 @@ pub const TypeErasedQueue = struct {
987989 const total_filled = elements.len - remaining.len;
988990 if (total_filled >= min) return total_filled;
989991
990 var node: std.DoublyLinkedList(PutNode).Node = .{
991 .data = .{ .remaining = remaining, .condition = .{} },
992 };
993 q.putters.append(&node);
994 try node.data.condition.wait(io, &q.mutex);
995 remaining = node.data.remaining;
992 var pending: Put = .{ .remaining = remaining, .condition = .{}, .node = .{} };
993 q.putters.append(&pending.node);
994 try pending.condition.wait(io, &q.mutex);
995 remaining = pending.remaining;
996996 }
997997 }
998998
......@@ -1035,16 +1035,16 @@ pub const TypeErasedQueue = struct {
10351035 }
10361036 // Copy directly from putters into buffer.
10371037 while (remaining.len > 0) {
1038 const putter = q.putters.popFirst() orelse break;
1039 const copy_len = @min(putter.data.remaining.len, remaining.len);
1040 @memcpy(remaining[0..copy_len], putter.data.remaining[0..copy_len]);
1041 putter.data.remaining = putter.data.remaining[copy_len..];
1038 const putter: *Put = @fieldParentPtr("node", q.putters.popFirst() orelse break);
1039 const copy_len = @min(putter.remaining.len, remaining.len);
1040 @memcpy(remaining[0..copy_len], putter.remaining[0..copy_len]);
1041 putter.remaining = putter.remaining[copy_len..];
10421042 remaining = remaining[copy_len..];
1043 if (putter.data.remaining.len == 0) {
1044 putter.data.condition.signal(io);
1043 if (putter.remaining.len == 0) {
1044 putter.condition.signal(io);
10451045 } else {
10461046 assert(remaining.len == 0);
1047 q.putters.prepend(putter);
1047 q.putters.prepend(&putter.node);
10481048 return fillRingBufferFromPutters(q, io, buffer.len);
10491049 }
10501050 }
......@@ -1052,12 +1052,10 @@ pub const TypeErasedQueue = struct {
10521052 const total_filled = buffer.len - remaining.len;
10531053 if (total_filled >= min) return total_filled;
10541054
1055 var node: std.DoublyLinkedList(GetNode).Node = .{
1056 .data = .{ .remaining = remaining, .condition = .{} },
1057 };
1058 q.getters.append(&node);
1059 try node.data.condition.wait(io, &q.mutex);
1060 remaining = node.data.remaining;
1055 var pending: Get = .{ .remaining = remaining, .condition = .{}, .node = .{} };
1056 q.getters.append(&pending.node);
1057 try pending.condition.wait(io, &q.mutex);
1058 remaining = pending.remaining;
10611059 }
10621060 }
10631061
......@@ -1067,26 +1065,26 @@ pub const TypeErasedQueue = struct {
10671065 /// buffers been fully copied.
10681066 fn fillRingBufferFromPutters(q: *TypeErasedQueue, io: Io, len: usize) usize {
10691067 while (true) {
1070 const putter = q.putters.popFirst() orelse return len;
1068 const putter: *Put = @fieldParentPtr("node", q.putters.popFirst() orelse return len);
10711069 const available = q.buffer[q.put_index..];
1072 const copy_len = @min(available.len, putter.data.remaining.len);
1073 @memcpy(available[0..copy_len], putter.data.remaining[0..copy_len]);
1074 putter.data.remaining = putter.data.remaining[copy_len..];
1070 const copy_len = @min(available.len, putter.remaining.len);
1071 @memcpy(available[0..copy_len], putter.remaining[0..copy_len]);
1072 putter.remaining = putter.remaining[copy_len..];
10751073 q.put_index += copy_len;
1076 if (putter.data.remaining.len == 0) {
1077 putter.data.condition.signal(io);
1074 if (putter.remaining.len == 0) {
1075 putter.condition.signal(io);
10781076 continue;
10791077 }
10801078 const second_available = q.buffer[0..q.get_index];
1081 const second_copy_len = @min(second_available.len, putter.data.remaining.len);
1082 @memcpy(second_available[0..second_copy_len], putter.data.remaining[0..second_copy_len]);
1083 putter.data.remaining = putter.data.remaining[copy_len..];
1079 const second_copy_len = @min(second_available.len, putter.remaining.len);
1080 @memcpy(second_available[0..second_copy_len], putter.remaining[0..second_copy_len]);
1081 putter.remaining = putter.remaining[copy_len..];
10841082 q.put_index = copy_len;
1085 if (putter.data.remaining.len == 0) {
1086 putter.data.condition.signal(io);
1083 if (putter.remaining.len == 0) {
1084 putter.condition.signal(io);
10871085 continue;
10881086 }
1089 q.putters.prepend(putter);
1087 q.putters.prepend(&putter.node);
10901088 return len;
10911089 }
10921090 }
lib/std/Io/EventLoop.zig+3-4
......@@ -13,7 +13,7 @@ main_fiber_buffer: [@sizeOf(Fiber) + Fiber.max_result_size]u8 align(@alignOf(Fib
1313threads: Thread.List,
1414detached: struct {
1515 mutex: std.Io.Mutex,
16 list: std.DoublyLinkedList(void),
16 list: std.DoublyLinkedList,
1717},
1818
1919/// Empirically saw >128KB being used by the self-hosted backend to panic.
......@@ -226,7 +226,6 @@ pub fn deinit(el: *EventLoop) void {
226226 detached.detached_queue_node = .{
227227 .prev = &detached.detached_queue_node,
228228 .next = &detached.detached_queue_node,
229 .data = {},
230229 };
231230 break :detached_future @ptrCast(detached.fiber);
232231 }, &.{}, .@"1");
......@@ -753,7 +752,7 @@ const DetachedClosure = struct {
753752 event_loop: *EventLoop,
754753 fiber: *Fiber,
755754 start: *const fn (context: *const anyopaque) void,
756 detached_queue_node: std.DoublyLinkedList(void).Node,
755 detached_queue_node: std.DoublyLinkedList.Node,
757756
758757 fn contextPointer(closure: *DetachedClosure) [*]align(Fiber.max_context_align.toByteUnits()) u8 {
759758 return @alignCast(@as([*]u8, @ptrCast(closure)) + @sizeOf(DetachedClosure));
......@@ -818,7 +817,7 @@ fn go(
818817 .event_loop = event_loop,
819818 .fiber = fiber,
820819 .start = start,
821 .detached_queue_node = .{ .data = {} },
820 .detached_queue_node = .{},
822821 };
823822 {
824823 event_loop.detached.mutex.lock(event_loop.io()) catch |err| switch (err) {