feature. See also
. The project being documented here (as the example) is the Zig library itself.
Threaded.fileDowngradeLock
fn fileDowngradeLock(userdata: ?*anyopaque, file: File) File.DowngradeLockError!void
File
Code
fn fileDowngradeLock(userdata: ?*anyopaque, file: File) File.DowngradeLockError!void {
if (native_os == .wasi) return;
const t: *Threaded = @ptrCast(@alignCast(userdata));
_ = t;
if (is_windows) {
// implement this function, we first obtain another lock in shared
// mode. This changes the exclusivity flag, but increments the
// semaphore to 2. So we follow up with an NtUnlockFile which
// decrements the semaphore but does not modify the exclusivity flag.
var io_status_block: windows.IO_STATUS_BLOCK = undefined;
const syscall: Syscall = try .start();
while (true) switch (windows.ntdll.NtLockFile(
file.handle,
null,
null,
null,
&io_status_block,
&windows_lock_range_off,
&windows_lock_range_len,
null,
.TRUE,
.FALSE,
)) {
.SUCCESS => break syscall.finish(),
.CANCELLED => {
try syscall.checkCancel();
continue;
},
.INSUFFICIENT_RESOURCES => |err| return syscall.ntstatusBug(err),
.LOCK_NOT_GRANTED => |err| return syscall.ntstatusBug(err),
.ACCESS_VIOLATION => |err| return syscall.ntstatusBug(err),
else => |status| return syscall.unexpectedNtstatus(status),
};
while (true) switch (windows.ntdll.NtUnlockFile(
file.handle,
&io_status_block,
&windows_lock_range_off,
&windows_lock_range_len,
0,
)) {
.SUCCESS => return,
.CANCELLED => continue,
.RANGE_NOT_LOCKED => if (is_debug) unreachable else return,
.ACCESS_VIOLATION => if (is_debug) unreachable else return,
else => if (is_debug) unreachable else return,
};
}
const operation = posix.LOCK.SH | posix.LOCK.NB;
const syscall: Syscall = try .start();
while (true) {
switch (posix.errno(posix.system.flock(file.handle, operation))) {
.SUCCESS => {
syscall.finish();
return;
},
.INTR => {
try syscall.checkCancel();
continue;
},
else => |e| {
syscall.finish();
switch (e) {
.AGAIN => |err| return errnoBug(err),
.BADF => |err| return errnoBug(err),
.INVAL => |err| return errnoBug(err),
.NOLCK => |err| return errnoBug(err),
.OPNOTSUPP => |err| return errnoBug(err),
else => |err| return posix.unexpectedErrno(err),
}
},
}
}
}