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 {...@@ -917,17 +917,19 @@ pub const TypeErasedQueue = struct {
917 put_index: usize,917 put_index: usize,
918 get_index: usize,918 get_index: usize,
919919
920 putters: std.DoublyLinkedList(PutNode),920 putters: std.DoublyLinkedList,
921 getters: std.DoublyLinkedList(GetNode),921 getters: std.DoublyLinkedList,
922922
923 const PutNode = struct {923 const Put = struct {
924 remaining: []const u8,924 remaining: []const u8,
925 condition: Condition,925 condition: Condition,
926 node: std.DoublyLinkedList.Node,
926 };927 };
927928
928 const GetNode = struct {929 const Get = struct {
929 remaining: []u8,930 remaining: []u8,
930 condition: Condition,931 condition: Condition,
932 node: std.DoublyLinkedList.Node,
931 };933 };
932934
933 pub fn init(buffer: []u8) TypeErasedQueue {935 pub fn init(buffer: []u8) TypeErasedQueue {
...@@ -952,16 +954,16 @@ pub const TypeErasedQueue = struct {...@@ -952,16 +954,16 @@ pub const TypeErasedQueue = struct {
952954
953 var remaining = elements;955 var remaining = elements;
954 while (true) {956 while (true) {
955 const getter = q.getters.popFirst() orelse break;957 const getter: *Get = @fieldParentPtr("node", q.getters.popFirst() orelse break);
956 const copy_len = @min(getter.data.remaining.len, remaining.len);958 const copy_len = @min(getter.remaining.len, remaining.len);
957 @memcpy(getter.data.remaining[0..copy_len], remaining[0..copy_len]);959 @memcpy(getter.remaining[0..copy_len], remaining[0..copy_len]);
958 remaining = remaining[copy_len..];960 remaining = remaining[copy_len..];
959 getter.data.remaining = getter.data.remaining[copy_len..];961 getter.remaining = getter.remaining[copy_len..];
960 if (getter.data.remaining.len == 0) {962 if (getter.remaining.len == 0) {
961 getter.data.condition.signal(io);963 getter.condition.signal(io);
962 continue;964 continue;
963 }965 }
964 q.getters.prepend(getter);966 q.getters.prepend(&getter.node);
965 assert(remaining.len == 0);967 assert(remaining.len == 0);
966 return elements.len;968 return elements.len;
967 }969 }
...@@ -987,12 +989,10 @@ pub const TypeErasedQueue = struct {...@@ -987,12 +989,10 @@ pub const TypeErasedQueue = struct {
987 const total_filled = elements.len - remaining.len;989 const total_filled = elements.len - remaining.len;
988 if (total_filled >= min) return total_filled;990 if (total_filled >= min) return total_filled;
989991
990 var node: std.DoublyLinkedList(PutNode).Node = .{992 var pending: Put = .{ .remaining = remaining, .condition = .{}, .node = .{} };
991 .data = .{ .remaining = remaining, .condition = .{} },993 q.putters.append(&pending.node);
992 };994 try pending.condition.wait(io, &q.mutex);
993 q.putters.append(&node);995 remaining = pending.remaining;
994 try node.data.condition.wait(io, &q.mutex);
995 remaining = node.data.remaining;
996 }996 }
997 }997 }
998998
...@@ -1035,16 +1035,16 @@ pub const TypeErasedQueue = struct {...@@ -1035,16 +1035,16 @@ pub const TypeErasedQueue = struct {
1035 }1035 }
1036 // Copy directly from putters into buffer.1036 // Copy directly from putters into buffer.
1037 while (remaining.len > 0) {1037 while (remaining.len > 0) {
1038 const putter = q.putters.popFirst() orelse break;1038 const putter: *Put = @fieldParentPtr("node", q.putters.popFirst() orelse break);
1039 const copy_len = @min(putter.data.remaining.len, remaining.len);1039 const copy_len = @min(putter.remaining.len, remaining.len);
1040 @memcpy(remaining[0..copy_len], putter.data.remaining[0..copy_len]);1040 @memcpy(remaining[0..copy_len], putter.remaining[0..copy_len]);
1041 putter.data.remaining = putter.data.remaining[copy_len..];1041 putter.remaining = putter.remaining[copy_len..];
1042 remaining = remaining[copy_len..];1042 remaining = remaining[copy_len..];
1043 if (putter.data.remaining.len == 0) {1043 if (putter.remaining.len == 0) {
1044 putter.data.condition.signal(io);1044 putter.condition.signal(io);
1045 } else {1045 } else {
1046 assert(remaining.len == 0);1046 assert(remaining.len == 0);
1047 q.putters.prepend(putter);1047 q.putters.prepend(&putter.node);
1048 return fillRingBufferFromPutters(q, io, buffer.len);1048 return fillRingBufferFromPutters(q, io, buffer.len);
1049 }1049 }
1050 }1050 }
...@@ -1052,12 +1052,10 @@ pub const TypeErasedQueue = struct {...@@ -1052,12 +1052,10 @@ pub const TypeErasedQueue = struct {
1052 const total_filled = buffer.len - remaining.len;1052 const total_filled = buffer.len - remaining.len;
1053 if (total_filled >= min) return total_filled;1053 if (total_filled >= min) return total_filled;
10541054
1055 var node: std.DoublyLinkedList(GetNode).Node = .{1055 var pending: Get = .{ .remaining = remaining, .condition = .{}, .node = .{} };
1056 .data = .{ .remaining = remaining, .condition = .{} },1056 q.getters.append(&pending.node);
1057 };1057 try pending.condition.wait(io, &q.mutex);
1058 q.getters.append(&node);1058 remaining = pending.remaining;
1059 try node.data.condition.wait(io, &q.mutex);
1060 remaining = node.data.remaining;
1061 }1059 }
1062 }1060 }
10631061
...@@ -1067,26 +1065,26 @@ pub const TypeErasedQueue = struct {...@@ -1067,26 +1065,26 @@ pub const TypeErasedQueue = struct {
1067 /// buffers been fully copied.1065 /// buffers been fully copied.
1068 fn fillRingBufferFromPutters(q: *TypeErasedQueue, io: Io, len: usize) usize {1066 fn fillRingBufferFromPutters(q: *TypeErasedQueue, io: Io, len: usize) usize {
1069 while (true) {1067 while (true) {
1070 const putter = q.putters.popFirst() orelse return len;1068 const putter: *Put = @fieldParentPtr("node", q.putters.popFirst() orelse return len);
1071 const available = q.buffer[q.put_index..];1069 const available = q.buffer[q.put_index..];
1072 const copy_len = @min(available.len, putter.data.remaining.len);1070 const copy_len = @min(available.len, putter.remaining.len);
1073 @memcpy(available[0..copy_len], putter.data.remaining[0..copy_len]);1071 @memcpy(available[0..copy_len], putter.remaining[0..copy_len]);
1074 putter.data.remaining = putter.data.remaining[copy_len..];1072 putter.remaining = putter.remaining[copy_len..];
1075 q.put_index += copy_len;1073 q.put_index += copy_len;
1076 if (putter.data.remaining.len == 0) {1074 if (putter.remaining.len == 0) {
1077 putter.data.condition.signal(io);1075 putter.condition.signal(io);
1078 continue;1076 continue;
1079 }1077 }
1080 const second_available = q.buffer[0..q.get_index];1078 const second_available = q.buffer[0..q.get_index];
1081 const second_copy_len = @min(second_available.len, putter.data.remaining.len);1079 const second_copy_len = @min(second_available.len, putter.remaining.len);
1082 @memcpy(second_available[0..second_copy_len], putter.data.remaining[0..second_copy_len]);1080 @memcpy(second_available[0..second_copy_len], putter.remaining[0..second_copy_len]);
1083 putter.data.remaining = putter.data.remaining[copy_len..];1081 putter.remaining = putter.remaining[copy_len..];
1084 q.put_index = copy_len;1082 q.put_index = copy_len;
1085 if (putter.data.remaining.len == 0) {1083 if (putter.remaining.len == 0) {
1086 putter.data.condition.signal(io);1084 putter.condition.signal(io);
1087 continue;1085 continue;
1088 }1086 }
1089 q.putters.prepend(putter);1087 q.putters.prepend(&putter.node);
1090 return len;1088 return len;
1091 }1089 }
1092 }1090 }
lib/std/Io/EventLoop.zig+3-4
...@@ -13,7 +13,7 @@ main_fiber_buffer: [@sizeOf(Fiber) + Fiber.max_result_size]u8 align(@alignOf(Fib...@@ -13,7 +13,7 @@ main_fiber_buffer: [@sizeOf(Fiber) + Fiber.max_result_size]u8 align(@alignOf(Fib
13threads: Thread.List,13threads: Thread.List,
14detached: struct {14detached: struct {
15 mutex: std.Io.Mutex,15 mutex: std.Io.Mutex,
16 list: std.DoublyLinkedList(void),16 list: std.DoublyLinkedList,
17},17},
1818
19/// Empirically saw >128KB being used by the self-hosted backend to panic.19/// Empirically saw >128KB being used by the self-hosted backend to panic.
...@@ -226,7 +226,6 @@ pub fn deinit(el: *EventLoop) void {...@@ -226,7 +226,6 @@ pub fn deinit(el: *EventLoop) void {
226 detached.detached_queue_node = .{226 detached.detached_queue_node = .{
227 .prev = &detached.detached_queue_node,227 .prev = &detached.detached_queue_node,
228 .next = &detached.detached_queue_node,228 .next = &detached.detached_queue_node,
229 .data = {},
230 };229 };
231 break :detached_future @ptrCast(detached.fiber);230 break :detached_future @ptrCast(detached.fiber);
232 }, &.{}, .@"1");231 }, &.{}, .@"1");
...@@ -753,7 +752,7 @@ const DetachedClosure = struct {...@@ -753,7 +752,7 @@ const DetachedClosure = struct {
753 event_loop: *EventLoop,752 event_loop: *EventLoop,
754 fiber: *Fiber,753 fiber: *Fiber,
755 start: *const fn (context: *const anyopaque) void,754 start: *const fn (context: *const anyopaque) void,
756 detached_queue_node: std.DoublyLinkedList(void).Node,755 detached_queue_node: std.DoublyLinkedList.Node,
757756
758 fn contextPointer(closure: *DetachedClosure) [*]align(Fiber.max_context_align.toByteUnits()) u8 {757 fn contextPointer(closure: *DetachedClosure) [*]align(Fiber.max_context_align.toByteUnits()) u8 {
759 return @alignCast(@as([*]u8, @ptrCast(closure)) + @sizeOf(DetachedClosure));758 return @alignCast(@as([*]u8, @ptrCast(closure)) + @sizeOf(DetachedClosure));
...@@ -818,7 +817,7 @@ fn go(...@@ -818,7 +817,7 @@ fn go(
818 .event_loop = event_loop,817 .event_loop = event_loop,
819 .fiber = fiber,818 .fiber = fiber,
820 .start = start,819 .start = start,
821 .detached_queue_node = .{ .data = {} },820 .detached_queue_node = .{},
822 };821 };
823 {822 {
824 event_loop.detached.mutex.lock(event_loop.io()) catch |err| switch (err) {823 event_loop.detached.mutex.lock(event_loop.io()) catch |err| switch (err) {