authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-15 11:00:00-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:49-07:00
log80069c1e69140ac240e5397270ea919ddbfce89b
tree2f62d43aa70b8911b05e8e5205b0594ba1355cbe
parentadaef433d24ce88230fe64ce20214d695cf83bc0

std.Io.Queue: add "uncancelable" variants to "get"

useful for resource management

1 files changed, 34 insertions(+), 8 deletions(-)

lib/std/Io.zig+34-8
......@@ -1315,10 +1315,23 @@ pub const TypeErasedQueue = struct {
13151315
13161316 pub fn get(q: *@This(), io: Io, buffer: []u8, min: usize) Cancelable!usize {
13171317 assert(buffer.len >= min);
1318
1318 if (buffer.len == 0) return 0;
13191319 try q.mutex.lock(io);
13201320 defer q.mutex.unlock(io);
1321 return getLocked(q, io, buffer, min, false);
1322 }
1323
1324 pub fn getUncancelable(q: *@This(), io: Io, buffer: []u8, min: usize) usize {
1325 assert(buffer.len >= min);
1326 if (buffer.len == 0) return 0;
1327 q.mutex.lockUncancelable(io);
1328 defer q.mutex.unlock(io);
1329 return getLocked(q, io, buffer, min, true) catch |err| switch (err) {
1330 error.Canceled => unreachable,
1331 };
1332 }
13211333
1334 pub fn getLocked(q: *@This(), io: Io, buffer: []u8, min: usize, uncancelable: bool) Cancelable!usize {
13221335 // The ring buffer gets first priority, then data should come from any
13231336 // queued putters, then finally the ring buffer should be filled with
13241337 // data from putters so they can be resumed.
......@@ -1371,7 +1384,10 @@ pub const TypeErasedQueue = struct {
13711384
13721385 var pending: Get = .{ .remaining = remaining, .condition = .{}, .node = .{} };
13731386 q.getters.append(&pending.node);
1374 try pending.condition.wait(io, &q.mutex);
1387 if (uncancelable)
1388 pending.condition.waitUncancelable(io, &q.mutex)
1389 else
1390 try pending.condition.wait(io, &q.mutex);
13751391 remaining = pending.remaining;
13761392 }
13771393 }
......@@ -1439,6 +1455,14 @@ pub fn Queue(Elem: type) type {
14391455 return @divExact(q.type_erased.putUncancelable(io, @ptrCast(elements), min * @sizeOf(Elem)), @sizeOf(Elem));
14401456 }
14411457
1458 pub fn putOne(q: *@This(), io: Io, item: Elem) Cancelable!void {
1459 assert(try q.put(io, &.{item}, 1) == 1);
1460 }
1461
1462 pub fn putOneUncancelable(q: *@This(), io: Io, item: Elem) void {
1463 assert(q.putUncancelable(io, &.{item}, 1) == 1);
1464 }
1465
14421466 /// Receives elements from the beginning of the queue. The function
14431467 /// returns when at least `min` elements have been populated inside
14441468 /// `buffer`.
......@@ -1450,12 +1474,8 @@ pub fn Queue(Elem: type) type {
14501474 return @divExact(try q.type_erased.get(io, @ptrCast(buffer), min * @sizeOf(Elem)), @sizeOf(Elem));
14511475 }
14521476
1453 pub fn putOne(q: *@This(), io: Io, item: Elem) Cancelable!void {
1454 assert(try q.put(io, &.{item}, 1) == 1);
1455 }
1456
1457 pub fn putOneUncancelable(q: *@This(), io: Io, item: Elem) void {
1458 assert(q.putUncancelable(io, &.{item}, 1) == 1);
1477 pub fn getUncancelable(q: *@This(), io: Io, buffer: []Elem, min: usize) usize {
1478 return @divExact(q.type_erased.getUncancelable(io, @ptrCast(buffer), min * @sizeOf(Elem)), @sizeOf(Elem));
14591479 }
14601480
14611481 pub fn getOne(q: *@This(), io: Io) Cancelable!Elem {
......@@ -1464,6 +1484,12 @@ pub fn Queue(Elem: type) type {
14641484 return buf[0];
14651485 }
14661486
1487 pub fn getOneUncancelable(q: *@This(), io: Io) Elem {
1488 var buf: [1]Elem = undefined;
1489 assert(q.getUncancelable(io, &buf, 1) == 1);
1490 return buf[0];
1491 }
1492
14671493 /// Returns buffer length in `Elem` units.
14681494 pub fn capacity(q: *const @This()) usize {
14691495 return @divExact(q.type_erased.buffer.len, @sizeOf(Elem));