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-07-20 10:38:39-07:00
log3f524ac5dc243585495bb16c15d00f13923fee6e
tree33afaa921414614c5822a8abcf738a6cfb3b9112
parent3178cf07f297a1a5f3e852a4f33a14dd9463ba07

Io: update for new linked list API


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

lib/std/Io.zig+40-42
......@@ -1270,17 +1270,19 @@ pub const TypeErasedQueue = struct {
12701270 put_index: usize,
12711271 get_index: usize,
12721272
1273 putters: std.DoublyLinkedList(PutNode),
1274 getters: std.DoublyLinkedList(GetNode),
1273 putters: std.DoublyLinkedList,
1274 getters: std.DoublyLinkedList,
12751275
1276 const PutNode = struct {
1276 const Put = struct {
12771277 remaining: []const u8,
12781278 condition: Condition,
1279 node: std.DoublyLinkedList.Node,
12791280 };
12801281
1281 const GetNode = struct {
1282 const Get = struct {
12821283 remaining: []u8,
12831284 condition: Condition,
1285 node: std.DoublyLinkedList.Node,
12841286 };
12851287
12861288 pub fn init(buffer: []u8) TypeErasedQueue {
......@@ -1305,16 +1307,16 @@ pub const TypeErasedQueue = struct {
13051307
13061308 var remaining = elements;
13071309 while (true) {
1308 const getter = q.getters.popFirst() orelse break;
1309 const copy_len = @min(getter.data.remaining.len, remaining.len);
1310 @memcpy(getter.data.remaining[0..copy_len], remaining[0..copy_len]);
1310 const getter: *Get = @fieldParentPtr("node", q.getters.popFirst() orelse break);
1311 const copy_len = @min(getter.remaining.len, remaining.len);
1312 @memcpy(getter.remaining[0..copy_len], remaining[0..copy_len]);
13111313 remaining = remaining[copy_len..];
1312 getter.data.remaining = getter.data.remaining[copy_len..];
1313 if (getter.data.remaining.len == 0) {
1314 getter.data.condition.signal(io);
1314 getter.remaining = getter.remaining[copy_len..];
1315 if (getter.remaining.len == 0) {
1316 getter.condition.signal(io);
13151317 continue;
13161318 }
1317 q.getters.prepend(getter);
1319 q.getters.prepend(&getter.node);
13181320 assert(remaining.len == 0);
13191321 return elements.len;
13201322 }
......@@ -1340,12 +1342,10 @@ pub const TypeErasedQueue = struct {
13401342 const total_filled = elements.len - remaining.len;
13411343 if (total_filled >= min) return total_filled;
13421344
1343 var node: std.DoublyLinkedList(PutNode).Node = .{
1344 .data = .{ .remaining = remaining, .condition = .{} },
1345 };
1346 q.putters.append(&node);
1347 try node.data.condition.wait(io, &q.mutex);
1348 remaining = node.data.remaining;
1345 var pending: Put = .{ .remaining = remaining, .condition = .{}, .node = .{} };
1346 q.putters.append(&pending.node);
1347 try pending.condition.wait(io, &q.mutex);
1348 remaining = pending.remaining;
13491349 }
13501350 }
13511351
......@@ -1388,16 +1388,16 @@ pub const TypeErasedQueue = struct {
13881388 }
13891389 // Copy directly from putters into buffer.
13901390 while (remaining.len > 0) {
1391 const putter = q.putters.popFirst() orelse break;
1392 const copy_len = @min(putter.data.remaining.len, remaining.len);
1393 @memcpy(remaining[0..copy_len], putter.data.remaining[0..copy_len]);
1394 putter.data.remaining = putter.data.remaining[copy_len..];
1391 const putter: *Put = @fieldParentPtr("node", q.putters.popFirst() orelse break);
1392 const copy_len = @min(putter.remaining.len, remaining.len);
1393 @memcpy(remaining[0..copy_len], putter.remaining[0..copy_len]);
1394 putter.remaining = putter.remaining[copy_len..];
13951395 remaining = remaining[copy_len..];
1396 if (putter.data.remaining.len == 0) {
1397 putter.data.condition.signal(io);
1396 if (putter.remaining.len == 0) {
1397 putter.condition.signal(io);
13981398 } else {
13991399 assert(remaining.len == 0);
1400 q.putters.prepend(putter);
1400 q.putters.prepend(&putter.node);
14011401 return fillRingBufferFromPutters(q, io, buffer.len);
14021402 }
14031403 }
......@@ -1405,12 +1405,10 @@ pub const TypeErasedQueue = struct {
14051405 const total_filled = buffer.len - remaining.len;
14061406 if (total_filled >= min) return total_filled;
14071407
1408 var node: std.DoublyLinkedList(GetNode).Node = .{
1409 .data = .{ .remaining = remaining, .condition = .{} },
1410 };
1411 q.getters.append(&node);
1412 try node.data.condition.wait(io, &q.mutex);
1413 remaining = node.data.remaining;
1408 var pending: Get = .{ .remaining = remaining, .condition = .{}, .node = .{} };
1409 q.getters.append(&pending.node);
1410 try pending.condition.wait(io, &q.mutex);
1411 remaining = pending.remaining;
14141412 }
14151413 }
14161414
......@@ -1420,26 +1418,26 @@ pub const TypeErasedQueue = struct {
14201418 /// buffers been fully copied.
14211419 fn fillRingBufferFromPutters(q: *TypeErasedQueue, io: Io, len: usize) usize {
14221420 while (true) {
1423 const putter = q.putters.popFirst() orelse return len;
1421 const putter: *Put = @fieldParentPtr("node", q.putters.popFirst() orelse return len);
14241422 const available = q.buffer[q.put_index..];
1425 const copy_len = @min(available.len, putter.data.remaining.len);
1426 @memcpy(available[0..copy_len], putter.data.remaining[0..copy_len]);
1427 putter.data.remaining = putter.data.remaining[copy_len..];
1423 const copy_len = @min(available.len, putter.remaining.len);
1424 @memcpy(available[0..copy_len], putter.remaining[0..copy_len]);
1425 putter.remaining = putter.remaining[copy_len..];
14281426 q.put_index += copy_len;
1429 if (putter.data.remaining.len == 0) {
1430 putter.data.condition.signal(io);
1427 if (putter.remaining.len == 0) {
1428 putter.condition.signal(io);
14311429 continue;
14321430 }
14331431 const second_available = q.buffer[0..q.get_index];
1434 const second_copy_len = @min(second_available.len, putter.data.remaining.len);
1435 @memcpy(second_available[0..second_copy_len], putter.data.remaining[0..second_copy_len]);
1436 putter.data.remaining = putter.data.remaining[copy_len..];
1432 const second_copy_len = @min(second_available.len, putter.remaining.len);
1433 @memcpy(second_available[0..second_copy_len], putter.remaining[0..second_copy_len]);
1434 putter.remaining = putter.remaining[copy_len..];
14371435 q.put_index = copy_len;
1438 if (putter.data.remaining.len == 0) {
1439 putter.data.condition.signal(io);
1436 if (putter.remaining.len == 0) {
1437 putter.condition.signal(io);
14401438 continue;
14411439 }
1442 q.putters.prepend(putter);
1440 q.putters.prepend(&putter.node);
14431441 return len;
14441442 }
14451443 }
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) {