feature. See also
. The project being documented here (as the example) is the Zig library itself.
Uring.CachedFd
const CachedFd = struct
File
Code
const CachedFd = struct {
once: Once,
const Once = enum(fd_t) {
uninitialized = -1,
initializing = -2,
_,
fn fromFd(fd: fd_t) Once {
return @fromBackingInt(@intCast(@as(u31, @intCast(fd))));
}
fn toFd(once: Once) fd_t {
return @as(u31, @intCast(@backingInt(once)));
}
};
const init: CachedFd = .{ .once = .uninitialized };
fn close(cached_fd: *CachedFd) void {
switch (cached_fd.once) {
.uninitialized => {},
.initializing => unreachable,
_ => |fd| {
assert(@backingInt(fd) >= 0);
_ = linux.close(@backingInt(fd));
cached_fd.* = .init;
},
}
}
fn open(
cached_fd: *CachedFd,
ev: *Evented,
cancel_region: *CancelRegion,
path: [*:0]const u8,
flags: linux.O,
) File.OpenError!fd_t {
var once = @atomicLoad(Once, &cached_fd.once, .monotonic);
while (true) {
switch (once) {
.uninitialized => {},
.initializing => try futexWait(
ev,
@ptrCast(&cached_fd.once),
@bitCast(@backingInt(once)),
.none,
),
_ => |fd| {
@branchHint(.likely);
return fd.toFd();
},
}
once = @cmpxchgWeak(
Once,
&cached_fd.once,
.uninitialized,
.initializing,
.monotonic,
.monotonic,
) orelse {
errdefer {
@atomicStore(Once, &cached_fd.once, .uninitialized, .monotonic);
futexWake(ev, @ptrCast(&cached_fd.once), 1);
}
const fd = ev.openat(cancel_region, linux.AT.FDCWD, path, flags, 0) catch |err| switch (err) {
error.OperationUnsupported => return error.Unexpected,
else => |e| return e,
};
@atomicStore(Once, &cached_fd.once, .fromFd(fd), .monotonic);
futexWake(ev, @ptrCast(&cached_fd.once), std.math.maxInt(u32));
return fd;
};
}
}
}